Vulkan: Use multiple command pools, one per frame
Instead of resetting two command buffers, now we only have to call vkResetCommandPool once at the start of a frame. NV's recommends using one pool per frame/thread. May offer a very small boost in performance on some systems.
This commit is contained in:
parent
017ab71fcf
commit
3c92b35422
|
@ -33,14 +33,10 @@ CommandBufferManager::~CommandBufferManager()
|
|||
vkDeviceWaitIdle(g_vulkan_context->GetDevice());
|
||||
|
||||
DestroyCommandBuffers();
|
||||
DestroyCommandPool();
|
||||
}
|
||||
|
||||
bool CommandBufferManager::Initialize()
|
||||
{
|
||||
if (!CreateCommandPool())
|
||||
return false;
|
||||
|
||||
if (!CreateCommandBuffers())
|
||||
return false;
|
||||
|
||||
|
@ -50,48 +46,31 @@ bool CommandBufferManager::Initialize()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferManager::CreateCommandPool()
|
||||
{
|
||||
VkCommandPoolCreateInfo info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr,
|
||||
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
|
||||
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
g_vulkan_context->GetGraphicsQueueFamilyIndex()};
|
||||
|
||||
VkResult res =
|
||||
vkCreateCommandPool(g_vulkan_context->GetDevice(), &info, nullptr, &m_command_pool);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandBufferManager::DestroyCommandPool()
|
||||
{
|
||||
if (m_command_pool)
|
||||
{
|
||||
vkDestroyCommandPool(g_vulkan_context->GetDevice(), m_command_pool, nullptr);
|
||||
m_command_pool = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
bool CommandBufferManager::CreateCommandBuffers()
|
||||
{
|
||||
VkDevice device = g_vulkan_context->GetDevice();
|
||||
VkResult res;
|
||||
|
||||
for (FrameResources& resources : m_frame_resources)
|
||||
{
|
||||
resources.init_command_buffer_used = false;
|
||||
resources.needs_fence_wait = false;
|
||||
|
||||
VkCommandBufferAllocateInfo allocate_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, m_command_pool,
|
||||
VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0,
|
||||
g_vulkan_context->GetGraphicsQueueFamilyIndex()};
|
||||
res = vkCreateCommandPool(g_vulkan_context->GetDevice(), &pool_info, nullptr,
|
||||
&resources.command_pool);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
|
||||
return false;
|
||||
}
|
||||
|
||||
VkCommandBufferAllocateInfo buffer_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, resources.command_pool,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(resources.command_buffers.size())};
|
||||
|
||||
VkResult res =
|
||||
vkAllocateCommandBuffers(device, &allocate_info, resources.command_buffers.data());
|
||||
res = vkAllocateCommandBuffers(device, &buffer_info, resources.command_buffers.data());
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkAllocateCommandBuffers failed: ");
|
||||
|
@ -157,12 +136,17 @@ void CommandBufferManager::DestroyCommandBuffers()
|
|||
}
|
||||
if (resources.command_buffers[0] != VK_NULL_HANDLE)
|
||||
{
|
||||
vkFreeCommandBuffers(device, m_command_pool,
|
||||
vkFreeCommandBuffers(device, resources.command_pool,
|
||||
static_cast<u32>(resources.command_buffers.size()),
|
||||
resources.command_buffers.data());
|
||||
|
||||
resources.command_buffers.fill(VK_NULL_HANDLE);
|
||||
}
|
||||
if (resources.command_pool != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroyCommandPool(device, resources.command_pool, nullptr);
|
||||
resources.command_pool = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,16 +396,16 @@ void CommandBufferManager::ActivateCommandBuffer()
|
|||
if (res != VK_SUCCESS)
|
||||
LOG_VULKAN_ERROR(res, "vkResetFences failed: ");
|
||||
|
||||
// Reset command buffer to beginning since we can re-use the memory now
|
||||
// Reset command pools to beginning since we can re-use the memory now
|
||||
res = vkResetCommandPool(g_vulkan_context->GetDevice(), resources.command_pool, 0);
|
||||
if (res != VK_SUCCESS)
|
||||
LOG_VULKAN_ERROR(res, "vkResetCommandPool failed: ");
|
||||
|
||||
// Enable commands to be recorded to the two buffers again.
|
||||
VkCommandBufferBeginInfo begin_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
|
||||
resources.init_command_buffer_used = false;
|
||||
for (VkCommandBuffer command_buffer : resources.command_buffers)
|
||||
{
|
||||
res = vkResetCommandBuffer(command_buffer, 0);
|
||||
if (res != VK_SUCCESS)
|
||||
LOG_VULKAN_ERROR(res, "vkResetCommandBuffer failed: ");
|
||||
|
||||
res = vkBeginCommandBuffer(command_buffer, &begin_info);
|
||||
if (res != VK_SUCCESS)
|
||||
LOG_VULKAN_ERROR(res, "vkBeginCommandBuffer failed: ");
|
||||
|
@ -431,6 +415,9 @@ void CommandBufferManager::ActivateCommandBuffer()
|
|||
res = vkResetDescriptorPool(g_vulkan_context->GetDevice(), resources.descriptor_pool, 0);
|
||||
if (res != VK_SUCCESS)
|
||||
LOG_VULKAN_ERROR(res, "vkResetDescriptorPool failed: ");
|
||||
|
||||
// Reset upload command buffer state
|
||||
resources.init_command_buffer_used = false;
|
||||
}
|
||||
|
||||
void CommandBufferManager::ExecuteCommandBuffer(bool submit_off_thread, bool wait_for_completion)
|
||||
|
|
|
@ -33,7 +33,6 @@ public:
|
|||
|
||||
bool Initialize();
|
||||
|
||||
VkCommandPool GetCommandPool() const { return m_command_pool; }
|
||||
// These command buffers are allocated per-frame. They are valid until the command buffer
|
||||
// is submitted, after that you should call these functions again.
|
||||
VkCommandBuffer GetCurrentInitCommandBuffer()
|
||||
|
@ -100,9 +99,6 @@ public:
|
|||
void RemoveFencePointCallback(const void* key);
|
||||
|
||||
private:
|
||||
bool CreateCommandPool();
|
||||
void DestroyCommandPool();
|
||||
|
||||
bool CreateCommandBuffers();
|
||||
void DestroyCommandBuffers();
|
||||
|
||||
|
@ -113,11 +109,10 @@ private:
|
|||
|
||||
void OnCommandBufferExecuted(size_t index);
|
||||
|
||||
VkCommandPool m_command_pool = VK_NULL_HANDLE;
|
||||
|
||||
struct FrameResources
|
||||
{
|
||||
// [0] - Init (upload) command buffer, [1] - draw command buffer
|
||||
VkCommandPool command_pool;
|
||||
std::array<VkCommandBuffer, 2> command_buffers;
|
||||
VkDescriptorPool descriptor_pool;
|
||||
VkFence fence;
|
||||
|
|
Loading…
Reference in New Issue