vk_resource_manager: Implement a command buffer pool with VKFencedPool
This commit is contained in:
parent
a2b6de7e9f
commit
ae6c052ed9
2 changed files with 59 additions and 1 deletions
|
@ -13,8 +13,55 @@
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
// TODO(Rodrigo): Fine tune these numbers.
|
// TODO(Rodrigo): Fine tune these numbers.
|
||||||
|
constexpr std::size_t COMMAND_BUFFER_POOL_SIZE = 0x1000;
|
||||||
constexpr std::size_t FENCES_GROW_STEP = 0x40;
|
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;
|
||||||
|
|
||||||
VKResource::~VKResource() = default;
|
VKResource::~VKResource() = default;
|
||||||
|
@ -174,6 +221,7 @@ void VKFencedPool::Grow() {
|
||||||
|
|
||||||
VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} {
|
VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} {
|
||||||
GrowFences(FENCES_GROW_STEP);
|
GrowFences(FENCES_GROW_STEP);
|
||||||
|
command_buffer_pool = std::make_unique<CommandBufferPool>(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
VKResourceManager::~VKResourceManager() = default;
|
VKResourceManager::~VKResourceManager() = default;
|
||||||
|
@ -217,6 +265,10 @@ VKFence& VKResourceManager::CommitFence() {
|
||||||
return *found_fence;
|
return *found_fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::CommandBuffer VKResourceManager::CommitCommandBuffer(VKFence& fence) {
|
||||||
|
return command_buffer_pool->Commit(fence);
|
||||||
|
}
|
||||||
|
|
||||||
void VKResourceManager::GrowFences(std::size_t new_fences_count) {
|
void VKResourceManager::GrowFences(std::size_t new_fences_count) {
|
||||||
const auto dev = device.GetLogical();
|
const auto dev = device.GetLogical();
|
||||||
const auto& dld = device.GetDispatchLoader();
|
const auto& dld = device.GetDispatchLoader();
|
||||||
|
|
|
@ -15,6 +15,8 @@ class VKDevice;
|
||||||
class VKFence;
|
class VKFence;
|
||||||
class VKResourceManager;
|
class VKResourceManager;
|
||||||
|
|
||||||
|
class CommandBufferPool;
|
||||||
|
|
||||||
/// Interface for a Vulkan resource
|
/// Interface for a Vulkan resource
|
||||||
class VKResource {
|
class VKResource {
|
||||||
public:
|
public:
|
||||||
|
@ -162,13 +164,17 @@ public:
|
||||||
/// Commits a fence. It has to be sent to a queue and released.
|
/// Commits a fence. It has to be sent to a queue and released.
|
||||||
VKFence& CommitFence();
|
VKFence& CommitFence();
|
||||||
|
|
||||||
|
/// Commits an unused command buffer and protects it with a fence.
|
||||||
|
vk::CommandBuffer CommitCommandBuffer(VKFence& fence);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Allocates new fences.
|
/// Allocates new fences.
|
||||||
void GrowFences(std::size_t new_fences_count);
|
void GrowFences(std::size_t new_fences_count);
|
||||||
|
|
||||||
const VKDevice& device; ///< Device handler.
|
const VKDevice& device; ///< Device handler.
|
||||||
std::size_t fences_iterator = 0; ///< Index where a free fence is likely to be found.
|
std::size_t fences_iterator = 0; ///< Index where a free fence is likely to be found.
|
||||||
std::vector<std::unique_ptr<VKFence>> fences; ///< Pool of fences.
|
std::vector<std::unique_ptr<VKFence>> fences; ///< Pool of fences.
|
||||||
|
std::unique_ptr<CommandBufferPool> command_buffer_pool; ///< Pool of command buffers.
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
Loading…
Reference in a new issue