|
|
@@ -13,8 +13,55 @@
|
|
|
namespace Vulkan {
|
|
|
|
|
|
// TODO(Rodrigo): Fine tune these numbers.
|
|
|
+constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000;
|
|
|
constexpr std::size_t FENCES_GROW_STEP = 0x40;
|
|
|
|
|
|
+class CommandBufferPool final : public VKFencedPool {
|
|
|
+public:
|
|
|
+ CommandBufferPool(const VKDevice& device)
|
|
|
+ : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {}
|
|
|
+
|
|
|
+ void Allocate(std::size_t begin, std::size_t end) {
|
|
|
+ const auto dev = device.GetLogical();
|
|
|
+ const auto& dld = device.GetDispatchLoader();
|
|
|
+ const u32 graphics_family = device.GetGraphicsFamily();
|
|
|
+
|
|
|
+ auto pool = std::make_unique<Pool>();
|
|
|
+
|
|
|
+ // Command buffers are going to be commited, recorded, executed every single usage cycle.
|
|
|
+ // They are also going to be reseted when commited.
|
|
|
+ const auto pool_flags = vk::CommandPoolCreateFlagBits::eTransient |
|
|
|
+ vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
|
|
|
+ const vk::CommandPoolCreateInfo cmdbuf_pool_ci(pool_flags, graphics_family);
|
|
|
+ pool->handle = dev.createCommandPoolUnique(cmdbuf_pool_ci, nullptr, dld);
|
|
|
+
|
|
|
+ const vk::CommandBufferAllocateInfo cmdbuf_ai(*pool->handle,
|
|
|
+ vk::CommandBufferLevel::ePrimary,
|
|
|
+ static_cast<u32>(COMMAND_BUFFER_POOL_SIZE));
|
|
|
+ pool->cmdbufs =
|
|
|
+ dev.allocateCommandBuffersUnique<std::allocator<UniqueCommandBuffer>>(cmdbuf_ai, dld);
|
|
|
+
|
|
|
+ pools.push_back(std::move(pool));
|
|
|
+ }
|
|
|
+
|
|
|
+ vk::CommandBuffer Commit(VKFence& fence) {
|
|
|
+ const std::size_t index = CommitResource(fence);
|
|
|
+ const auto pool_index = index / COMMAND_BUFFER_POOL_SIZE;
|
|
|
+ const auto sub_index = index % COMMAND_BUFFER_POOL_SIZE;
|
|
|
+ return *pools[pool_index]->cmdbufs[sub_index];
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ struct Pool {
|
|
|
+ UniqueCommandPool handle;
|
|
|
+ std::vector<UniqueCommandBuffer> cmdbufs;
|
|
|
+ };
|
|
|
+
|
|
|
+ const VKDevice& device;
|
|
|
+
|
|
|
+ std::vector<std::unique_ptr<Pool>> pools;
|
|
|
+};
|
|
|
+
|
|
|
VKResource::VKResource() = default;
|
|
|
|
|
|
VKResource::~VKResource() = default;
|
|
|
@@ -174,6 +221,7 @@ void VKFencedPool::Grow() {
|
|
|
|
|
|
VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} {
|
|
|
GrowFences(FENCES_GROW_STEP);
|
|
|
+ command_buffer_pool = std::make_unique<CommandBufferPool>(device);
|
|
|
}
|
|
|
|
|
|
VKResourceManager::~VKResourceManager() = default;
|
|
|
@@ -217,6 +265,10 @@ VKFence& VKResourceManager::CommitFence() {
|
|
|
return *found_fence;
|
|
|
}
|
|
|
|
|
|
+vk::CommandBuffer VKResourceManager::CommitCommandBuffer(VKFence& fence) {
|
|
|
+ return command_buffer_pool->Commit(fence);
|
|
|
+}
|
|
|
+
|
|
|
void VKResourceManager::GrowFences(std::size_t new_fences_count) {
|
|
|
const auto dev = device.GetLogical();
|
|
|
const auto& dld = device.GetDispatchLoader();
|