// // Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // PersistentCommandPool.cpp: // Implements the class methods for PersistentCommandPool // #include "libANGLE/renderer/vulkan/PersistentCommandPool.h" namespace rx { namespace vk { PersistentCommandPool::PersistentCommandPool() {} PersistentCommandPool::~PersistentCommandPool() { ASSERT(!mCommandPool.valid() && mFreeBuffers.empty()); } angle::Result PersistentCommandPool::init(vk::Context *context, bool hasProtectedContent, uint32_t queueFamilyIndex) { ASSERT(!mCommandPool.valid()); // Initialize the command pool now that we know the queue family index. VkCommandPoolCreateInfo commandPoolInfo = {}; commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; // TODO (https://issuetracker.google.com/issues/166793850) We currently reset individual // command buffers from this pool. Alternatively we could reset the entire command pool. commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; if (hasProtectedContent) { commandPoolInfo.flags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT; } commandPoolInfo.queueFamilyIndex = queueFamilyIndex; ANGLE_VK_TRY(context, mCommandPool.init(context->getDevice(), commandPoolInfo)); for (uint32_t i = 0; i < kInitBufferNum; i++) { ANGLE_TRY(allocateCommandBuffer(context)); } return angle::Result::Continue; } void PersistentCommandPool::destroy(VkDevice device) { if (!valid()) return; ASSERT(mCommandPool.valid()); for (vk::PrimaryCommandBuffer &cmdBuf : mFreeBuffers) { cmdBuf.destroy(device, mCommandPool); } mFreeBuffers.clear(); mCommandPool.destroy(device); } angle::Result PersistentCommandPool::allocate(vk::Context *context, vk::PrimaryCommandBuffer *commandBufferOut) { if (mFreeBuffers.empty()) { ANGLE_TRY(allocateCommandBuffer(context)); ASSERT(!mFreeBuffers.empty()); } *commandBufferOut = std::move(mFreeBuffers.back()); mFreeBuffers.pop_back(); return angle::Result::Continue; } angle::Result PersistentCommandPool::collect(vk::Context *context, vk::PrimaryCommandBuffer &&buffer) { // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT NOT set, The CommandBuffer // can still hold the memory resource ANGLE_VK_TRY(context, vkResetCommandBuffer(buffer.getHandle(), 0)); mFreeBuffers.emplace_back(std::move(buffer)); return angle::Result::Continue; } angle::Result PersistentCommandPool::allocateCommandBuffer(vk::Context *context) { vk::PrimaryCommandBuffer commandBuffer; { // Only used for primary CommandBuffer allocation VkCommandBufferAllocateInfo commandBufferInfo = {}; commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; commandBufferInfo.commandPool = mCommandPool.getHandle(); commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; commandBufferInfo.commandBufferCount = 1; ANGLE_VK_TRY(context, commandBuffer.init(context->getDevice(), commandBufferInfo)); } mFreeBuffers.emplace_back(std::move(commandBuffer)); return angle::Result::Continue; } } // namespace vk } // namespace rx