use ash::vk;
const COUNT_BASE: u32 = 16;
#[derive(Debug)]
pub struct DescriptorPool {
sub_pools: Vec<vk::DescriptorPool>,
growth_iter: usize,
}
impl super::Device {
fn create_descriptor_sub_pool(&self, max_sets: u32) -> vk::DescriptorPool {
log::info!("Creating a descriptor pool for at most {} sets", max_sets);
let mut descriptor_sizes = vec![
vk::DescriptorPoolSize {
ty: vk::DescriptorType::STORAGE_BUFFER,
descriptor_count: max_sets,
},
vk::DescriptorPoolSize {
ty: vk::DescriptorType::SAMPLED_IMAGE,
descriptor_count: 2 * max_sets,
},
vk::DescriptorPoolSize {
ty: vk::DescriptorType::SAMPLER,
descriptor_count: max_sets,
},
vk::DescriptorPoolSize {
ty: vk::DescriptorType::STORAGE_IMAGE,
descriptor_count: max_sets,
},
];
if self.inline_uniform_blocks {
descriptor_sizes.push(vk::DescriptorPoolSize {
ty: vk::DescriptorType::INLINE_UNIFORM_BLOCK_EXT,
descriptor_count: max_sets * crate::limits::PLAIN_DATA_SIZE,
});
} else {
descriptor_sizes.push(vk::DescriptorPoolSize {
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: max_sets,
});
}
if self.ray_tracing.is_some() {
descriptor_sizes.push(vk::DescriptorPoolSize {
ty: vk::DescriptorType::ACCELERATION_STRUCTURE_KHR,
descriptor_count: max_sets,
});
}
let mut inline_uniform_block_info = vk::DescriptorPoolInlineUniformBlockCreateInfoEXT {
max_inline_uniform_block_bindings: max_sets,
..Default::default()
};
let mut descriptor_pool_info = vk::DescriptorPoolCreateInfo::default()
.max_sets(max_sets)
.flags(self.workarounds.extra_descriptor_pool_create_flags)
.pool_sizes(&descriptor_sizes);
if self.inline_uniform_blocks {
descriptor_pool_info = descriptor_pool_info.push_next(&mut inline_uniform_block_info);
}
unsafe {
self.core
.create_descriptor_pool(&descriptor_pool_info, None)
.unwrap()
}
}
pub(super) fn create_descriptor_pool(&self) -> DescriptorPool {
let vk_pool = self.create_descriptor_sub_pool(COUNT_BASE);
DescriptorPool {
sub_pools: vec![vk_pool],
growth_iter: 0,
}
}
pub(super) fn destroy_descriptor_pool(&self, pool: &mut DescriptorPool) {
for sub_pool in pool.sub_pools.drain(..) {
unsafe { self.core.destroy_descriptor_pool(sub_pool, None) };
}
}
pub(super) fn allocate_descriptor_set(
&self,
pool: &mut DescriptorPool,
layout: &super::DescriptorSetLayout,
) -> vk::DescriptorSet {
let descriptor_set_layouts = [layout.raw];
loop {
let descriptor_set_info = vk::DescriptorSetAllocateInfo::default()
.descriptor_pool(pool.sub_pools[0])
.set_layouts(&descriptor_set_layouts);
match unsafe { self.core.allocate_descriptor_sets(&descriptor_set_info) } {
Ok(vk_sets) => return vk_sets[0],
Err(vk::Result::ERROR_OUT_OF_POOL_MEMORY)
| Err(vk::Result::ERROR_FRAGMENTED_POOL) => {}
Err(other) => panic!("Unexpected descriptor allocation error: {:?}", other),
};
let next_max_sets = COUNT_BASE.pow(pool.growth_iter as u32 + 1);
pool.growth_iter += 1;
let vk_pool = self.create_descriptor_sub_pool(next_max_sets);
pool.sub_pools.insert(0, vk_pool);
}
}
pub(super) fn reset_descriptor_pool(&self, pool: &mut DescriptorPool) {
for vk_pool in pool.sub_pools.drain(1..) {
unsafe {
self.core.destroy_descriptor_pool(vk_pool, None);
}
}
unsafe {
self.core
.reset_descriptor_pool(pool.sub_pools[0], vk::DescriptorPoolResetFlags::empty())
.unwrap();
}
}
}