use std::sync::{Arc, Mutex};
use anyhow::Result;
use ash::vk;
use crate::{DeletionQueue, DescriptorSet, Device, Error};
use crate::descriptor::descriptor_pool::{DescriptorPool, DescriptorPoolSize};
use crate::descriptor::descriptor_set::DescriptorSetBinding;
use crate::util::cache::Cache;
#[derive(Debug)]
struct DescriptorCacheInner {
device: Device,
cache: Cache<DescriptorSet>,
pool: DescriptorPool,
deferred_pool_delete: DeletionQueue<DescriptorPool>,
}
#[derive(Debug, Clone)]
pub struct DescriptorCache {
inner: Arc<Mutex<DescriptorCacheInner>>,
}
fn grow_pool_size(
mut old_size: DescriptorPoolSize,
request: &DescriptorSetBinding,
) -> DescriptorPoolSize {
for (ty, count) in old_size.0.iter_mut() {
if request.bindings.iter().any(|binding| binding.ty == *ty) {
*count *= 2;
trace!("Growing descriptor pool for type {:?} to new size {}", ty, *count);
}
}
old_size
}
impl DescriptorCacheInner {
pub fn get_descriptor_set(
&mut self,
mut bindings: DescriptorSetBinding,
) -> Result<&DescriptorSet> {
if bindings.bindings.is_empty() {
return Err(Error::EmptyDescriptorBinding.into());
}
if bindings.layout == vk::DescriptorSetLayout::null() {
return Err(Error::NoDescriptorSetLayout.into());
}
loop {
bindings.pool = unsafe { self.pool.handle() };
let is_ok = { self.cache.get_or_create(&bindings, ()).is_ok() };
if is_ok {
return Ok(self.cache.get_or_create(&bindings, ()).unwrap());
} else {
let new_size = grow_pool_size(self.pool.size().clone(), &bindings);
let mut new_pool = DescriptorPool::new(self.device.clone(), new_size)?;
std::mem::swap(&mut new_pool, &mut self.pool);
self.deferred_pool_delete.push(new_pool);
}
}
}
}
impl DescriptorCache {
pub fn new(device: Device) -> Result<Self> {
let inner = DescriptorCacheInner {
device: device.clone(),
cache: Cache::new(device.clone()),
pool: DescriptorPool::new(device.clone(), DescriptorPoolSize::new(&device, 1))?,
deferred_pool_delete: DeletionQueue::new(16),
};
Ok(Self {
inner: Arc::new(Mutex::new(inner)),
})
}
pub fn with_descriptor_set<F: FnOnce(&DescriptorSet) -> Result<()>>(
&self,
bindings: DescriptorSetBinding,
f: F,
) -> Result<()> {
let mut inner = self.inner.lock().unwrap();
let set = inner.get_descriptor_set(bindings)?;
f(set)
}
pub fn next_frame(&self) {
let mut inner = self.inner.lock().unwrap();
inner.cache.next_frame();
inner.deferred_pool_delete.next_frame();
}
}