vk_descriptor_manager: Cache descriptor sets
This commit is contained in:
@@ -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
|
||||
|
@@ -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{};
|
||||
};
|
||||
|
||||
|
@@ -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},
|
||||
}};
|
||||
|
||||
|
Reference in New Issue
Block a user