11 #include "fml/thread_local.h"
12 #include "fml/trace_event.h"
15 #include "vulkan/vulkan_structs.hpp"
25 vk::UniqueCommandPool&& pool,
26 std::vector<vk::UniqueCommandBuffer>&& buffers,
27 std::weak_ptr<CommandPoolRecyclerVK> recycler)
28 : pool_(
std::move(pool)),
29 buffers_(
std::move(buffers)),
30 recycler_(
std::move(recycler)) {}
33 auto const recycler = recycler_.lock();
44 recycler->Reclaim(std::move(pool_));
52 vk::UniqueCommandPool pool_;
57 std::vector<vk::UniqueCommandBuffer> buffers_;
58 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);
79 context->GetResourceManager(), std::move(reset_pool_when_dropped));
84 auto const context = context_.lock();
89 Lock lock(pool_mutex_);
94 auto const device = context->GetDevice();
95 vk::CommandBufferAllocateInfo info;
96 info.setCommandPool(pool_.get());
97 info.setCommandBufferCount(1u);
98 info.setLevel(vk::CommandBufferLevel::ePrimary);
99 auto [result, buffers] = device.allocateCommandBuffersUnique(info);
100 if (result != vk::Result::eSuccess) {
103 return std::move(buffers[0]);
107 Lock lock(pool_mutex_);
114 collected_buffers_.push_back(std::move(buffer));
118 Lock lock(pool_mutex_);
123 for (
auto& buffer : collected_buffers_) {
126 collected_buffers_.clear();
131 std::unordered_map<uint64_t, std::shared_ptr<CommandPoolVK>>;
137 static std::unordered_map<
const ContextVK*,
138 std::vector<std::weak_ptr<CommandPoolVK>>>
143 auto const strong_context = context_.lock();
144 if (!strong_context) {
153 auto const hash = strong_context->GetHash();
154 auto const it = pool_map.find(hash);
155 if (it != pool_map.end()) {
160 auto pool = Create();
165 auto const resource =
166 std::make_shared<CommandPoolVK>(std::move(*pool), context_);
167 pool_map.emplace(hash, resource);
171 g_all_pools_map[strong_context.get()].push_back(resource);
178 std::optional<vk::UniqueCommandPool> CommandPoolRecyclerVK::Create() {
180 if (
auto pool = Reuse()) {
185 auto context = context_.lock();
189 vk::CommandPoolCreateInfo info;
190 info.setQueueFamilyIndex(context->GetGraphicsQueue()->GetIndex().family);
191 info.setFlags(vk::CommandPoolCreateFlagBits::eTransient);
193 auto device = context->GetDevice();
194 auto [result, pool] = device.createCommandPoolUnique(info);
195 if (result != vk::Result::eSuccess) {
198 return std::move(pool);
201 std::optional<vk::UniqueCommandPool> CommandPoolRecyclerVK::Reuse() {
203 Lock recycled_lock(recycled_mutex_);
204 if (recycled_.empty()) {
209 auto pool = std::move(recycled_.back());
210 recycled_.pop_back();
211 return std::move(pool);
216 auto strong_context = context_.lock();
217 if (!strong_context) {
220 auto device = strong_context->GetDevice();
221 device.resetCommandPool(pool.get());
224 Lock recycled_lock(recycled_mutex_);
225 recycled_.push_back(std::move(pool));
249 auto found = g_all_pools_map.find(context);
250 if (found != g_all_pools_map.end()) {
251 for (
auto& weak_pool : found->second) {
252 auto pool = weak_pool.lock();
260 g_all_pools_map.erase(found);