1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // PersistentCommandPool.cpp:
7 // Implements the class methods for PersistentCommandPool
8 //
9
10 #include "libANGLE/renderer/vulkan/PersistentCommandPool.h"
11
12 namespace rx
13 {
14
15 namespace vk
16 {
17
PersistentCommandPool()18 PersistentCommandPool::PersistentCommandPool() {}
19
~PersistentCommandPool()20 PersistentCommandPool::~PersistentCommandPool()
21 {
22 ASSERT(!mCommandPool.valid() && mFreeBuffers.empty());
23 }
24
init(vk::Context * context,uint32_t queueFamilyIndex)25 angle::Result PersistentCommandPool::init(vk::Context *context, uint32_t queueFamilyIndex)
26 {
27 ASSERT(!mCommandPool.valid());
28
29 // Initialize the command pool now that we know the queue family index.
30 VkCommandPoolCreateInfo commandPoolInfo = {};
31 commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
32 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
33 commandPoolInfo.queueFamilyIndex = queueFamilyIndex;
34
35 ANGLE_VK_TRY(context, mCommandPool.init(context->getDevice(), commandPoolInfo));
36
37 for (uint32_t i = 0; i < kInitBufferNum; i++)
38 {
39 ANGLE_TRY(allocateCommandBuffer(context));
40 }
41
42 return angle::Result::Continue;
43 }
44
destroy(VkDevice device)45 void PersistentCommandPool::destroy(VkDevice device)
46 {
47 if (!valid())
48 return;
49
50 ASSERT(mCommandPool.valid());
51
52 for (vk::PrimaryCommandBuffer &cmdBuf : mFreeBuffers)
53 {
54 cmdBuf.destroy(device, mCommandPool);
55 }
56 mFreeBuffers.clear();
57
58 mCommandPool.destroy(device);
59 }
60
allocate(vk::Context * context,vk::PrimaryCommandBuffer * commandBufferOut)61 angle::Result PersistentCommandPool::allocate(vk::Context *context,
62 vk::PrimaryCommandBuffer *commandBufferOut)
63 {
64 if (mFreeBuffers.empty())
65 {
66 ANGLE_TRY(allocateCommandBuffer(context));
67 ASSERT(!mFreeBuffers.empty());
68 }
69
70 *commandBufferOut = std::move(mFreeBuffers.back());
71 mFreeBuffers.pop_back();
72
73 return angle::Result::Continue;
74 }
75
collect(vk::Context * context,vk::PrimaryCommandBuffer && buffer)76 angle::Result PersistentCommandPool::collect(vk::Context *context,
77 vk::PrimaryCommandBuffer &&buffer)
78 {
79 // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT NOT set, The CommandBuffer
80 // can still hold the memory resource
81 ANGLE_VK_TRY(context, vkResetCommandBuffer(buffer.getHandle(), 0));
82
83 mFreeBuffers.emplace_back(std::move(buffer));
84 return angle::Result::Continue;
85 }
86
allocateCommandBuffer(vk::Context * context)87 angle::Result PersistentCommandPool::allocateCommandBuffer(vk::Context *context)
88 {
89 vk::PrimaryCommandBuffer commandBuffer;
90 {
91 // Only used for primary CommandBuffer allocation
92 VkCommandBufferAllocateInfo commandBufferInfo = {};
93 commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
94 commandBufferInfo.commandPool = mCommandPool.getHandle();
95 commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
96 commandBufferInfo.commandBufferCount = 1;
97
98 ANGLE_VK_TRY(context, commandBuffer.init(context->getDevice(), commandBufferInfo));
99 }
100
101 mFreeBuffers.emplace_back(std::move(commandBuffer));
102
103 return angle::Result::Continue;
104 }
105
106 } // namespace vk
107
108 } // namespace rx
109