vk_descriptor_manager: Cache descriptor sets
This commit is contained in:
@@ -115,18 +115,21 @@ void DescriptorManager::BindDescriptorSets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> bound_sets;
|
|
||||||
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
for (u32 i = 0; i < MAX_DESCRIPTOR_SETS; i++) {
|
||||||
if (descriptor_set_dirty[i] || is_dirty) {
|
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]);
|
device.updateDescriptorSetWithTemplate(set, update_templates[i], update_data[i][0]);
|
||||||
descriptor_sets[i] = set;
|
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,
|
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline_layout, 0, bound_sets,
|
||||||
{});
|
{});
|
||||||
});
|
});
|
||||||
@@ -185,22 +188,29 @@ void DescriptorManager::BuildLayouts() {
|
|||||||
pipeline_layout = device.createPipelineLayout(layout_info);
|
pipeline_layout = device.createPipelineLayout(layout_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DescriptorSet DescriptorManager::AllocateSet(vk::DescriptorSetLayout layout) {
|
std::vector<vk::DescriptorSet> DescriptorManager::AllocateSets(vk::DescriptorSetLayout layout, u32 num_sets) {
|
||||||
const vk::Device device = instance.GetDevice();
|
static std::array<vk::DescriptorSetLayout, MAX_BATCH_SIZE> layouts;
|
||||||
const vk::DescriptorSetAllocateInfo alloc_info = {
|
layouts.fill(layout);
|
||||||
|
|
||||||
|
vk::DescriptorSetAllocateInfo alloc_info = {
|
||||||
.descriptorPool = current_pool,
|
.descriptorPool = current_pool,
|
||||||
.descriptorSetCount = 1,
|
.descriptorSetCount = num_sets,
|
||||||
.pSetLayouts = &layout,
|
.pSetLayouts = layouts.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return device.allocateDescriptorSets(alloc_info)[0];
|
return instance.GetDevice().allocateDescriptorSets(alloc_info);
|
||||||
} catch (vk::OutOfPoolMemoryError) {
|
} catch (vk::OutOfPoolMemoryError) {
|
||||||
pool_provider.RefreshTick();
|
pool_provider.RefreshTick();
|
||||||
current_pool = pool_provider.Commit();
|
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
|
} // namespace Vulkan
|
||||||
|
@@ -11,6 +11,7 @@ namespace Vulkan {
|
|||||||
|
|
||||||
constexpr u32 MAX_DESCRIPTORS = 7;
|
constexpr u32 MAX_DESCRIPTORS = 7;
|
||||||
constexpr u32 MAX_DESCRIPTOR_SETS = 3;
|
constexpr u32 MAX_DESCRIPTOR_SETS = 3;
|
||||||
|
constexpr u32 MAX_BATCH_SIZE = 32;
|
||||||
|
|
||||||
union DescriptorData {
|
union DescriptorData {
|
||||||
vk::DescriptorImageInfo image_info;
|
vk::DescriptorImageInfo image_info;
|
||||||
@@ -32,8 +33,13 @@ public:
|
|||||||
DescriptorManager(const Instance& instance, Scheduler& scheduler);
|
DescriptorManager(const Instance& instance, Scheduler& scheduler);
|
||||||
~DescriptorManager();
|
~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
|
/// 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
|
/// Binds a resource to the provided binding
|
||||||
void SetBinding(u32 set, u32 binding, DescriptorData data);
|
void SetBinding(u32 set, u32 binding, DescriptorData data);
|
||||||
@@ -60,6 +66,7 @@ private:
|
|||||||
std::array<vk::DescriptorUpdateTemplate, MAX_DESCRIPTOR_SETS> update_templates;
|
std::array<vk::DescriptorUpdateTemplate, MAX_DESCRIPTOR_SETS> update_templates;
|
||||||
std::array<DescriptorSetData, MAX_DESCRIPTOR_SETS> update_data{};
|
std::array<DescriptorSetData, MAX_DESCRIPTOR_SETS> update_data{};
|
||||||
std::array<vk::DescriptorSet, MAX_DESCRIPTOR_SETS> descriptor_sets{};
|
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{};
|
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
|
// Choose a sane pool size good for most games
|
||||||
static constexpr std::array<vk::DescriptorPoolSize, 4> pool_sizes = {{
|
static constexpr std::array<vk::DescriptorPoolSize, 4> pool_sizes = {{
|
||||||
{vk::DescriptorType::eUniformBuffer, 1024},
|
{vk::DescriptorType::eUniformBuffer, 4096},
|
||||||
{vk::DescriptorType::eCombinedImageSampler, 2048},
|
{vk::DescriptorType::eCombinedImageSampler, 8192},
|
||||||
{vk::DescriptorType::eUniformTexelBuffer, 1024},
|
{vk::DescriptorType::eUniformTexelBuffer, 4096},
|
||||||
{vk::DescriptorType::eStorageImage, 1024},
|
{vk::DescriptorType::eStorageImage, 1024},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user