206 lines
5.5 KiB
C++
206 lines
5.5 KiB
C++
/* Copyright (c) 2019-2025, Arm Limited and Contributors
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 the "License";
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "descriptor_pool.h"
|
|
|
|
#include "descriptor_set_layout.h"
|
|
#include "device.h"
|
|
|
|
namespace vkb
|
|
{
|
|
DescriptorPool::DescriptorPool(vkb::core::DeviceC &device,
|
|
const DescriptorSetLayout &descriptor_set_layout,
|
|
uint32_t pool_size) :
|
|
device{device},
|
|
descriptor_set_layout{&descriptor_set_layout}
|
|
{
|
|
const auto &bindings = descriptor_set_layout.get_bindings();
|
|
|
|
std::map<VkDescriptorType, std::uint32_t> descriptor_type_counts;
|
|
|
|
// Count each type of descriptor set
|
|
for (auto &binding : bindings)
|
|
{
|
|
descriptor_type_counts[binding.descriptorType] += binding.descriptorCount;
|
|
}
|
|
|
|
// Allocate pool sizes array
|
|
pool_sizes.resize(descriptor_type_counts.size());
|
|
|
|
auto pool_size_it = pool_sizes.begin();
|
|
|
|
// Fill pool size for each descriptor type count multiplied by the pool size
|
|
for (auto &it : descriptor_type_counts)
|
|
{
|
|
pool_size_it->type = it.first;
|
|
|
|
pool_size_it->descriptorCount = it.second * pool_size;
|
|
|
|
++pool_size_it;
|
|
}
|
|
|
|
pool_max_sets = pool_size;
|
|
}
|
|
|
|
DescriptorPool::~DescriptorPool()
|
|
{
|
|
// Destroy all descriptor pools
|
|
for (auto pool : pools)
|
|
{
|
|
vkDestroyDescriptorPool(device.get_handle(), pool, nullptr);
|
|
}
|
|
}
|
|
|
|
void DescriptorPool::reset()
|
|
{
|
|
// Reset all descriptor pools
|
|
for (auto pool : pools)
|
|
{
|
|
vkResetDescriptorPool(device.get_handle(), pool, 0);
|
|
}
|
|
|
|
// Clear internal tracking of descriptor set allocations
|
|
std::fill(pool_sets_count.begin(), pool_sets_count.end(), 0);
|
|
set_pool_mapping.clear();
|
|
|
|
// Reset the pool index from which descriptor sets are allocated
|
|
pool_index = 0;
|
|
}
|
|
|
|
const DescriptorSetLayout &DescriptorPool::get_descriptor_set_layout() const
|
|
{
|
|
assert(descriptor_set_layout && "Descriptor set layout is invalid");
|
|
return *descriptor_set_layout;
|
|
}
|
|
|
|
void DescriptorPool::set_descriptor_set_layout(const DescriptorSetLayout &set_layout)
|
|
{
|
|
descriptor_set_layout = &set_layout;
|
|
}
|
|
|
|
VkDescriptorSet DescriptorPool::allocate()
|
|
{
|
|
pool_index = find_available_pool(pool_index);
|
|
|
|
// Increment allocated set count for the current pool
|
|
++pool_sets_count[pool_index];
|
|
|
|
VkDescriptorSetLayout set_layout = get_descriptor_set_layout().get_handle();
|
|
|
|
VkDescriptorSetAllocateInfo alloc_info{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};
|
|
alloc_info.descriptorPool = pools[pool_index];
|
|
alloc_info.descriptorSetCount = 1;
|
|
alloc_info.pSetLayouts = &set_layout;
|
|
|
|
VkDescriptorSet handle = VK_NULL_HANDLE;
|
|
|
|
// Allocate a new descriptor set from the current pool
|
|
auto result = vkAllocateDescriptorSets(device.get_handle(), &alloc_info, &handle);
|
|
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
// Decrement allocated set count for the current pool
|
|
--pool_sets_count[pool_index];
|
|
|
|
return VK_NULL_HANDLE;
|
|
}
|
|
|
|
// Store mapping between the descriptor set and the pool
|
|
set_pool_mapping.emplace(handle, pool_index);
|
|
|
|
return handle;
|
|
}
|
|
|
|
VkResult DescriptorPool::free(VkDescriptorSet descriptor_set)
|
|
{
|
|
// Get the pool index of the descriptor set
|
|
auto it = set_pool_mapping.find(descriptor_set);
|
|
|
|
if (it == set_pool_mapping.end())
|
|
{
|
|
return VK_INCOMPLETE;
|
|
}
|
|
|
|
auto desc_pool_index = it->second;
|
|
|
|
// Free descriptor set from the pool
|
|
vkFreeDescriptorSets(device.get_handle(), pools[desc_pool_index], 1, &descriptor_set);
|
|
|
|
// Remove descriptor set mapping to the pool
|
|
set_pool_mapping.erase(it);
|
|
|
|
// Decrement allocated set count for the pool
|
|
--pool_sets_count[desc_pool_index];
|
|
|
|
// Change the current pool index to use the available pool
|
|
pool_index = desc_pool_index;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
std::uint32_t DescriptorPool::find_available_pool(std::uint32_t search_index)
|
|
{
|
|
// Create a new pool
|
|
if (pools.size() <= search_index)
|
|
{
|
|
VkDescriptorPoolCreateInfo create_info{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
|
|
|
|
create_info.poolSizeCount = to_u32(pool_sizes.size());
|
|
create_info.pPoolSizes = pool_sizes.data();
|
|
create_info.maxSets = pool_max_sets;
|
|
|
|
// We do not set FREE_DESCRIPTOR_SET_BIT as we do not need to free individual descriptor sets
|
|
create_info.flags = 0;
|
|
|
|
// Check descriptor set layout and enable the required flags
|
|
auto &binding_flags = descriptor_set_layout->get_binding_flags();
|
|
for (auto binding_flag : binding_flags)
|
|
{
|
|
if (binding_flag & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)
|
|
{
|
|
create_info.flags |= VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
|
|
}
|
|
}
|
|
|
|
VkDescriptorPool handle = VK_NULL_HANDLE;
|
|
|
|
// Create the Vulkan descriptor pool
|
|
auto result = vkCreateDescriptorPool(device.get_handle(), &create_info, nullptr, &handle);
|
|
|
|
if (result != VK_SUCCESS)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Store internally the Vulkan handle
|
|
pools.push_back(handle);
|
|
|
|
// Add set count for the descriptor pool
|
|
pool_sets_count.push_back(0);
|
|
|
|
return search_index;
|
|
}
|
|
else if (pool_sets_count[search_index] < pool_max_sets)
|
|
{
|
|
return search_index;
|
|
}
|
|
|
|
// Increment pool index
|
|
return find_available_pool(++search_index);
|
|
}
|
|
} // namespace vkb
|