vk_descriptor_manager: Cache descriptor sets

This commit is contained in:
GPUCode
2023-03-03 23:06:16 +02:00
parent 39edca2cf7
commit 32cb44d2b9
3 changed files with 33 additions and 16 deletions

View File

@@ -115,18 +115,21 @@ void DescriptorManager::BindDescriptorSets() {
}
const vk::Device device = instance.GetDevice();
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
if (descriptor_set_dirty[i] || is_dirty) {
vk::DescriptorSet set = AllocateSet(descriptor_set_layouts[i]);
std::vector<vk::DescriptorSet>& cache = set_cache[i];
if (cache.empty()) {
cache = AllocateSets(descriptor_set_layouts[i], MAX_BATCH_SIZE);
}
vk::DescriptorSet set = cache.back();
cache.pop_back();
device.updateDescriptorSetWithTemplate(set, update_templates[i], update_data[i][0]);
descriptor_sets[i] = set;
}
bound_sets[i] = descriptor_sets[i];
}
scheduler.Record([this, bound_sets](vk::CommandBuffer cmdbuf) {
scheduler.Record([this, bound_sets = descriptor_sets](vk::CommandBuffer cmdbuf) {
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline_layout, 0, bound_sets,
{});
});
@@ -185,22 +188,29 @@ void DescriptorManager::BuildLayouts() {
pipeline_layout = device.createPipelineLayout(layout_info);
}
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
const vk::Device device = instance.GetDevice();
const vk::DescriptorSetAllocateInfo alloc_info = {
std::vector<vk::DescriptorSet> DescriptorManager::AllocateSets(vk::DescriptorSetLayout layout, u32 num_sets) {
static std::array<vk::DescriptorSetLayout, MAX_BATCH_SIZE> layouts;
layouts.fill(layout);
vk::DescriptorSetAllocateInfo alloc_info = {
.descriptorPool = current_pool,
.descriptorSetCount = 1,
.pSetLayouts = &layout,
.descriptorSetCount = num_sets,
.pSetLayouts = layouts.data(),
};
try {
return device.allocateDescriptorSets(alloc_info)[0];
return instance.GetDevice().allocateDescriptorSets(alloc_info);
} catch (vk::OutOfPoolMemoryError) {
pool_provider.RefreshTick();
current_pool = pool_provider.Commit();
for (auto& cache : set_cache) {
cache.clear();
}
descriptor_set_dirty.set();
}
return AllocateSet(layout);
alloc_info.descriptorPool = current_pool;
return instance.GetDevice().allocateDescriptorSets(alloc_info);
}
} // namespace Vulkan

View File

@@ -11,6 +11,7 @@ namespace Vulkan {
constexpr u32 MAX_DESCRIPTORS = 7;
constexpr u32 MAX_DESCRIPTOR_SETS = 3;
constexpr u32 MAX_BATCH_SIZE = 32;
union DescriptorData {
vk::DescriptorImageInfo image_info;
@@ -32,8 +33,13 @@ public:
DescriptorManager(const Instance& instance, Scheduler& scheduler);
~DescriptorManager();
/// Allocates an array of descriptor sets of the provided layout
std::vector<vk::DescriptorSet> AllocateSets(vk::DescriptorSetLayout layout, u32 num_sets);
/// Allocates a descriptor set of the provided layout
vk::DescriptorSet AllocateSet(vk::DescriptorSetLayout layout);
vk::DescriptorSet AllocateSet(vk::DescriptorSetLayout layout) {
return AllocateSets(layout, 1)[0];
}
/// Binds a resource to the provided binding
void SetBinding(u32 set, u32 binding, DescriptorData data);
@@ -60,6 +66,7 @@ private:
std::array<vk::DescriptorUpdateTemplate, MAX_DESCRIPTOR_SETS> update_templates;
std::array<DescriptorSetData, MAX_DESCRIPTOR_SETS> update_data{};
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> descriptor_sets{};
std::array<std::vector<vk::DescriptorSet>, MAX_DESCRIPTOR_SETS> set_cache;
std::bitset<MAX_DESCRIPTOR_SETS> descriptor_set_dirty{};
};

View File

@@ -129,9 +129,9 @@ void DescriptorPool::Allocate(std::size_t begin, std::size_t end) {
// Choose a sane pool size good for most games
static constexpr std::array<vk::DescriptorPoolSize, 4> pool_sizes = {{
{vk::DescriptorType::eUniformBuffer, 1024},
{vk::DescriptorType::eCombinedImageSampler, 2048},
{vk::DescriptorType::eUniformTexelBuffer, 1024},
{vk::DescriptorType::eUniformBuffer, 4096},
{vk::DescriptorType::eCombinedImageSampler, 8192},
{vk::DescriptorType::eUniformTexelBuffer, 4096},
{vk::DescriptorType::eStorageImage, 1024},
}};