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(Context * context,ProtectionType protectionType,uint32_t queueFamilyIndex)25 angle::Result PersistentCommandPool::init(Context *context,
26 ProtectionType protectionType,
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 ASSERT(protectionType == ProtectionType::Unprotected ||
39 protectionType == ProtectionType::Protected);
40 if (protectionType == ProtectionType::Protected)
41 {
42 commandPoolInfo.flags |= VK_COMMAND_POOL_CREATE_PROTECTED_BIT;
43 }
44 commandPoolInfo.queueFamilyIndex = queueFamilyIndex;
45
46 ANGLE_VK_TRY(context, mCommandPool.init(context->getDevice(), commandPoolInfo));
47
48 for (uint32_t i = 0; i < kInitBufferNum; i++)
49 {
50 ANGLE_TRY(allocateCommandBuffer(context));
51 }
52
53 return angle::Result::Continue;
54 }
55
destroy(VkDevice device)56 void PersistentCommandPool::destroy(VkDevice device)
57 {
58 if (!valid())
59 return;
60
61 ASSERT(mCommandPool.valid());
62
63 for (PrimaryCommandBuffer &cmdBuf : mFreeBuffers)
64 {
65 cmdBuf.destroy(device, mCommandPool);
66 }
67 mFreeBuffers.clear();
68
69 mCommandPool.destroy(device);
70 }
71
allocate(Context * context,PrimaryCommandBuffer * commandBufferOut)72 angle::Result PersistentCommandPool::allocate(Context *context,
73 PrimaryCommandBuffer *commandBufferOut)
74 {
75 if (mFreeBuffers.empty())
76 {
77 ANGLE_TRY(allocateCommandBuffer(context));
78 ASSERT(!mFreeBuffers.empty());
79 }
80
81 *commandBufferOut = std::move(mFreeBuffers.back());
82 mFreeBuffers.pop_back();
83
84 return angle::Result::Continue;
85 }
86
collect(Context * context,PrimaryCommandBuffer && buffer)87 angle::Result PersistentCommandPool::collect(Context *context, PrimaryCommandBuffer &&buffer)
88 {
89 // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT NOT set, The CommandBuffer
90 // can still hold the memory resource
91 ANGLE_VK_TRY(context, buffer.reset());
92
93 mFreeBuffers.emplace_back(std::move(buffer));
94 return angle::Result::Continue;
95 }
96
allocateCommandBuffer(Context * context)97 angle::Result PersistentCommandPool::allocateCommandBuffer(Context *context)
98 {
99 PrimaryCommandBuffer commandBuffer;
100 {
101 // Only used for primary CommandBuffer allocation
102 VkCommandBufferAllocateInfo commandBufferInfo = {};
103 commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
104 commandBufferInfo.commandPool = mCommandPool.getHandle();
105 commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
106 commandBufferInfo.commandBufferCount = 1;
107
108 ANGLE_VK_TRY(context, commandBuffer.init(context->getDevice(), commandBufferInfo));
109 }
110
111 mFreeBuffers.emplace_back(std::move(commandBuffer));
112
113 return angle::Result::Continue;
114 }
115
116 } // namespace vk
117
118 } // namespace rx
119