Commit bc30e72c by Jamie Madill Committed by Commit Bot

Vulkan: Recycle command pools with vkResetCommandPool.

vkDestroyCommandPool has worse performance than reset. Instead of destroying and creating new command pools for every batch of work we can instead recycle unused command pools. This seems to improve performance on most systems. Bug: angleproject:3489 Change-Id: I7f8fe7f9385ca481e04f226a26426c3e92da19ff Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1636410Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com>
parent 94d5e051
......@@ -220,10 +220,11 @@ void ContextVk::onDestroy(const gl::Context *context)
mSubmitFence.reset(device);
mShaderLibrary.destroy(device);
mGpuEventQueryPool.destroy(device);
mCommandPool.destroy(device);
if (mCommandPool.valid())
for (vk::CommandPool &pool : mCommandPoolFreeList)
{
mCommandPool.destroy(device);
pool.destroy(device);
}
}
......@@ -240,13 +241,13 @@ angle::Result ContextVk::initialize()
{
TRACE_EVENT0("gpu.angle", "ContextVk::initialize");
// Note that this may reserve more sets than strictly necessary for a particular layout.
VkDescriptorPoolSize uniformSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
VkDescriptorPoolSize uniformSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
GetUniformBufferDescriptorCount()};
VkDescriptorPoolSize uniformBlockSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
mRenderer->getMaxUniformBlocks()};
VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
mRenderer->getMaxActiveTextures()};
VkDescriptorPoolSize driverSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1};
VkDescriptorPoolSize driverSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1};
ANGLE_TRY(mDynamicDescriptorPools[kUniformsDescriptorSetIndex].init(this, &uniformSetSize, 1));
ANGLE_TRY(mDynamicDescriptorPools[kUniformBlockDescriptorSetIndex].init(
this, &uniformBlockSetSize, 1));
......@@ -681,7 +682,16 @@ angle::Result ContextVk::submitFrame(const VkSubmitInfo &submitInfo,
poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
poolInfo.queueFamilyIndex = getRenderer()->getQueueFamilyIndex();
ANGLE_VK_TRY(this, mCommandPool.init(device, poolInfo));
if (mCommandPoolFreeList.empty())
{
ANGLE_VK_TRY(this, mCommandPool.init(device, poolInfo));
}
else
{
mCommandPool = std::move(mCommandPoolFreeList.back());
mCommandPoolFreeList.pop_back();
}
return angle::Result::Continue;
}
......@@ -698,7 +708,10 @@ void ContextVk::freeAllInFlightResources()
// If wait times out, it is probably not possible to recover from lost device
ASSERT(status == VK_SUCCESS || status == VK_ERROR_DEVICE_LOST);
}
batch.commandPool.destroy(device);
batch.commandPool.reset(device, 0);
mCommandPoolFreeList.emplace_back(std::move(batch.commandPool));
batch.fence.reset(device);
}
mInFlightCommands.clear();
......@@ -860,8 +873,7 @@ angle::Result ContextVk::synchronizeCpuGpuTime()
// Submit the command buffer
VkSubmitInfo submitInfo = {};
VkPipelineStageFlags waitMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
InitializeSubmitInfo(&submitInfo, commandBatch.get(), {}, &waitMask,
{});
InitializeSubmitInfo(&submitInfo, commandBatch.get(), {}, &waitMask, {});
ANGLE_TRY(submitFrame(submitInfo, std::move(commandBuffer)));
......
......@@ -469,7 +469,10 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
gl::AttributesMask mDirtyDefaultAttribsMask;
gl::AttribArray<vk::DynamicBuffer> mDefaultAttribBuffers;
// We use a single pool for recording commands. We also keep a free list for pool recycling.
vk::CommandPool mCommandPool;
std::vector<vk::CommandPool> mCommandPoolFreeList;
Serial mLastCompletedQueueSerial;
Serial mLastSubmittedQueueSerial;
Serial mCurrentQueueSerial;
......
......@@ -143,6 +143,7 @@ class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
CommandPool() = default;
void destroy(VkDevice device);
VkResult reset(VkDevice device, VkCommandPoolResetFlags flags);
VkResult init(VkDevice device, const VkCommandPoolCreateInfo &createInfo);
};
......@@ -555,6 +556,12 @@ ANGLE_INLINE void CommandPool::destroy(VkDevice device)
}
}
ANGLE_INLINE VkResult CommandPool::reset(VkDevice device, VkCommandPoolResetFlags flags)
{
ASSERT(valid());
return vkResetCommandPool(device, mHandle, flags);
}
ANGLE_INLINE VkResult CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createInfo)
{
ASSERT(!valid());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment