11 #include "fml/macros.h"
12 #include "fml/thread_local.h"
13 #include "fml/trace_event.h"
16 #include "vulkan/vulkan_structs.hpp"
26 vk::UniqueCommandPool&& pool,
27 std::vector<vk::UniqueCommandBuffer>&& buffers,
28 std::weak_ptr<CommandPoolRecyclerVK> recycler)
29 : pool_(
std::move(pool)),
30 buffers_(
std::move(buffers)),
31 recycler_(
std::move(recycler)) {}
34 auto const recycler = recycler_.lock();
44 recycler->Reclaim(std::move(pool_));
50 vk::UniqueCommandPool pool_;
55 std::vector<vk::UniqueCommandBuffer> buffers_;
56 std::weak_ptr<CommandPoolRecyclerVK> recycler_;
66 auto const context = context_.lock();
70 auto const recycler = context->GetCommandPoolRecycler();
76 std::move(pool_), std::move(collected_buffers_), recycler);
80 context->GetResourceManager(), std::move(reset_pool_when_dropped));
86 auto const context = context_.lock();
91 Lock lock(pool_mutex_);
96 auto const device = context->GetDevice();
97 vk::CommandBufferAllocateInfo info;
98 info.setCommandPool(pool_.get());
99 info.setCommandBufferCount(1u);
100 info.setLevel(vk::CommandBufferLevel::ePrimary);
101 auto [result, buffers] = device.allocateCommandBuffersUnique(info);
102 if (result != vk::Result::eSuccess) {
105 return std::move(buffers[0]);
109 Lock lock(pool_mutex_);
116 collected_buffers_.push_back(std::move(buffer));
120 Lock lock(pool_mutex_);
125 for (
auto& buffer : collected_buffers_) {
128 collected_buffers_.clear();
133 std::unordered_map<uint64_t, std::shared_ptr<CommandPoolVK>>;
139 static std::unordered_map<
const ContextVK*,
140 std::vector<std::weak_ptr<CommandPoolVK>>>
145 auto const strong_context = context_.lock();
146 if (!strong_context) {
155 auto const hash = strong_context->GetHash();
156 auto const it = pool_map.find(hash);
157 if (it != pool_map.end()) {
162 auto pool = Create();
167 auto const resource =
168 std::make_shared<CommandPoolVK>(std::move(*pool), context_);
169 pool_map.emplace(hash, resource);
173 g_all_pools_map[strong_context.get()].push_back(resource);
180 std::optional<vk::UniqueCommandPool> CommandPoolRecyclerVK::Create() {
182 if (
auto pool = Reuse()) {
187 auto context = context_.lock();
191 vk::CommandPoolCreateInfo info;
192 info.setQueueFamilyIndex(context->GetGraphicsQueue()->GetIndex().family);
193 info.setFlags(vk::CommandPoolCreateFlagBits::eTransient);
195 auto device = context->GetDevice();
196 auto [result, pool] = device.createCommandPoolUnique(info);
197 if (result != vk::Result::eSuccess) {
200 return std::move(pool);
203 std::optional<vk::UniqueCommandPool> CommandPoolRecyclerVK::Reuse() {
205 Lock recycled_lock(recycled_mutex_);
206 if (recycled_.empty()) {
211 auto pool = std::move(recycled_.back());
212 recycled_.pop_back();
213 return std::move(pool);
217 TRACE_EVENT0(
"impeller",
"ReclaimCommandPool");
220 auto strong_context = context_.lock();
221 if (!strong_context) {
224 auto device = strong_context->GetDevice();
225 device.resetCommandPool(pool.get());
228 Lock recycled_lock(recycled_mutex_);
229 recycled_.push_back(std::move(pool));
253 auto found = g_all_pools_map.find(context);
254 if (found != g_all_pools_map.end()) {
255 for (
auto& weak_pool : found->second) {
256 auto pool = weak_pool.lock();
264 g_all_pools_map.erase(found);