use wgpu::{Buffer, BufferUsages, Device};
pub struct BufferPool {
available: Vec<(Buffer, u64)>,
in_use_count: usize,
max_pool_size: usize,
}
impl BufferPool {
pub fn new(max_pool_size: usize) -> Self {
Self {
available: Vec::new(),
in_use_count: 0,
max_pool_size,
}
}
pub fn acquire(
&mut self,
device: &Device,
min_size: u64,
usage: BufferUsages,
label: &str,
) -> Buffer {
if let Some(idx) = self.available.iter().position(|(_, cap)| *cap >= min_size) {
self.in_use_count += 1;
return self.available.remove(idx).0;
}
self.in_use_count += 1;
device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size: min_size,
usage,
mapped_at_creation: false,
})
}
pub fn release(&mut self, buffer: Buffer, capacity: u64) {
self.in_use_count = self.in_use_count.saturating_sub(1);
if self.available.len() >= self.max_pool_size {
if let Some(min_idx) = self.available.iter()
.enumerate()
.min_by_key(|(_, (_, cap))| *cap)
.map(|(i, _)| i)
{
if self.available[min_idx].1 < capacity {
self.available.remove(min_idx);
} else {
return;
}
}
}
self.available.push((buffer, capacity));
}
pub fn available_count(&self) -> usize {
self.available.len()
}
pub fn in_use_count(&self) -> usize {
self.in_use_count
}
pub fn clear(&mut self) {
self.available.clear();
self.in_use_count = 0;
}
}
impl Default for BufferPool {
fn default() -> Self {
Self::new(64)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer_pool_default() {
let pool = BufferPool::default();
assert_eq!(pool.available_count(), 0);
assert_eq!(pool.in_use_count(), 0);
assert_eq!(pool.max_pool_size, 64);
}
#[test]
fn test_buffer_pool_custom_size() {
let pool = BufferPool::new(16);
assert_eq!(pool.max_pool_size, 16);
}
}