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,bool hasProtectedContent,uint32_t queueFamilyIndex)25 angle::Result PersistentCommandPool::init(vk::Context *context,
26 bool hasProtectedContent,
27 uint32_t queueFamilyIndex)
28 {
29 ASSERT(!mCommandPool.valid());
30
31 // Initialize the command pool now that we know the queue family index.
32 VkCommandPoolCreateInfo commandPoolInfo = {};
33 commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
34 // TODO (https://issuetracker.google.com/issues/166793850) We currently reset individual
35 // command buffers from this pool. Alternatively we could reset the entire command pool.
36 commandPoolInfo.flags =
37 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
38 if (hasProtectedContent)
39 {
40 commandPoolInfo.flags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT;
41 }
42 commandPoolInfo.queueFamilyIndex = queueFamilyIndex;
43
44 ANGLE_VK_TRY(context, mCommandPool.init(context->getDevice(), commandPoolInfo));
45
46 for (uint32_t i = 0; i < kInitBufferNum; i++)
47 {
48 ANGLE_TRY(allocateCommandBuffer(context));
49 }
50
51 return angle::Result::Continue;
52 }
53
destroy(VkDevice device)54 void PersistentCommandPool::destroy(VkDevice device)
55 {
56 if (!valid())
57 return;
58
59 ASSERT(mCommandPool.valid());
60
61 for (vk::PrimaryCommandBuffer &cmdBuf : mFreeBuffers)
62 {
63 cmdBuf.destroy(device, mCommandPool);
64 }
65 mFreeBuffers.clear();
66
67 mCommandPool.destroy(device);
68 }
69
allocate(vk::Context * context,vk::PrimaryCommandBuffer * commandBufferOut)70 angle::Result PersistentCommandPool::allocate(vk::Context *context,
71 vk::PrimaryCommandBuffer *commandBufferOut)
72 {
73 if (mFreeBuffers.empty())
74 {
75 ANGLE_TRY(allocateCommandBuffer(context));
76 ASSERT(!mFreeBuffers.empty());
77 }
78
79 *commandBufferOut = std::move(mFreeBuffers.back());
80 mFreeBuffers.pop_back();
81
82 return angle::Result::Continue;
83 }
84
collect(vk::Context * context,vk::PrimaryCommandBuffer && buffer)85 angle::Result PersistentCommandPool::collect(vk::Context *context,
86 vk::PrimaryCommandBuffer &&buffer)
87 {
88 // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT NOT set, The CommandBuffer
89 // can still hold the memory resource
90 ANGLE_VK_TRY(context, vkResetCommandBuffer(buffer.getHandle(), 0));
91
92 mFreeBuffers.emplace_back(std::move(buffer));
93 return angle::Result::Continue;
94 }
95
allocateCommandBuffer(vk::Context * context)96 angle::Result PersistentCommandPool::allocateCommandBuffer(vk::Context *context)
97 {
98 vk::PrimaryCommandBuffer commandBuffer;
99 {
100 // Only used for primary CommandBuffer allocation
101 VkCommandBufferAllocateInfo commandBufferInfo = {};
102 commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
103 commandBufferInfo.commandPool = mCommandPool.getHandle();
104 commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
105 commandBufferInfo.commandBufferCount = 1;
106
107 ANGLE_VK_TRY(context, commandBuffer.init(context->getDevice(), commandBufferInfo));
108 }
109
110 mFreeBuffers.emplace_back(std::move(commandBuffer));
111
112 return angle::Result::Continue;
113 }
114
115 } // namespace vk
116
117 } // namespace rx
118