use std::collections::HashMap;
use parking_lot::Mutex;
fn round_up_pow2(size: u64) -> u64 {
if size <= 1 {
return 1;
}
1u64 << (64 - (size - 1).leading_zeros())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct PoolKey {
size: u64,
usage: wgpu::BufferUsages,
}
pub struct BufferPool {
cache: Mutex<HashMap<PoolKey, Vec<wgpu::Buffer>>>,
}
impl BufferPool {
pub fn new() -> Self {
Self {
cache: Mutex::new(HashMap::new()),
}
}
pub fn acquire(
&self,
device: &wgpu::Device,
size_bytes: u64,
usage: wgpu::BufferUsages,
) -> wgpu::Buffer {
let rounded = round_up_pow2(size_bytes);
let key = PoolKey {
size: rounded,
usage,
};
if let Some(buf) = self.cache.lock().get_mut(&key).and_then(|v| v.pop()) {
return buf;
}
device.create_buffer(&wgpu::BufferDescriptor {
label: Some("pooled_buffer"),
size: rounded,
usage,
mapped_at_creation: false,
})
}
pub fn release(&self, buffer: wgpu::Buffer) {
let key = PoolKey {
size: buffer.size(),
usage: buffer.usage(),
};
self.cache.lock().entry(key).or_default().push(buffer);
}
pub fn clear(&self) {
self.cache.lock().clear();
}
pub fn cached_count(&self) -> usize {
self.cache.lock().values().map(|v| v.len()).sum()
}
}