15#include "vulkan/vulkan_enums.hpp"
16#include "vulkan/vulkan_handles.hpp"
17#include "vulkan/vulkan_structs.hpp"
31 vk::UniqueCommandPool&& pool,
32 std::vector<vk::UniqueCommandBuffer>&& buffers,
34 std::weak_ptr<CommandPoolRecyclerVK> recycler)
35 : pool_(
std::move(pool)),
36 buffers_(
std::move(buffers)),
37 unused_count_(unused_count),
38 recycler_(
std::move(recycler)) {}
41 auto const recycler = recycler_.lock();
53 recycler->Reclaim(std::move(pool_), std::move(buffers_),
62 vk::UniqueCommandPool pool_;
67 std::vector<vk::UniqueCommandBuffer> buffers_;
68 const size_t unused_count_;
69 std::weak_ptr<CommandPoolRecyclerVK> recycler_;
77 std::shared_ptr<DeviceHolderVK> device_holder = device_holder_.lock();
80 for (
auto& buffer : collected_buffers_) {
83 for (
auto& buffer : unused_command_buffers_) {
89 auto const context = context_.lock();
93 auto const recycler = context->GetCommandPoolRecycler();
99 size_t unused_count = unused_command_buffers_.size();
100 for (
auto i = 0u;
i < unused_command_buffers_.size();
i++) {
101 collected_buffers_.push_back(std::move(unused_command_buffers_[
i]));
103 unused_command_buffers_.clear();
106 std::move(pool_), std::move(collected_buffers_), unused_count, recycler);
109 context->GetResourceManager(), std::move(reset_pool_when_dropped));
114 auto const context = context_.lock();
119 Lock lock(pool_mutex_);
123 if (!unused_command_buffers_.empty()) {
124 vk::UniqueCommandBuffer buffer = std::move(unused_command_buffers_.back());
125 unused_command_buffers_.pop_back();
129 auto const device = context->GetDevice();
130 vk::CommandBufferAllocateInfo info;
131 info.setCommandPool(pool_.get());
132 info.setCommandBufferCount(1u);
133 info.setLevel(vk::CommandBufferLevel::ePrimary);
134 auto [result, buffers] =
device.allocateCommandBuffersUnique(info);
135 if (result != vk::Result::eSuccess) {
138 return std::move(buffers[0]);
142 Lock lock(pool_mutex_);
149 collected_buffers_.push_back(std::move(buffer));
152void CommandPoolVK::Destroy() {
154 Lock lock(pool_mutex_);
159 for (
auto& buffer : collected_buffers_) {
162 for (
auto& buffer : unused_command_buffers_) {
165 unused_command_buffers_.clear();
166 collected_buffers_.clear();
171 std::unordered_map<uint64_t, std::shared_ptr<CommandPoolVK>>;
186static std::unordered_map<
188 std::unordered_map<std::thread::id, std::weak_ptr<CommandPoolVK>>>
192 const std::shared_ptr<ContextVK>& context)
193 : context_(context), context_hash_(context->GetHash()) {}
199 auto it = g_all_pools_map.find(context.
GetHash());
200 return it != g_all_pools_map.end() ? it->second.size() : 0;
205 auto const strong_context = context_.lock();
206 if (!strong_context) {
215 auto const it = pool_map.find(context_hash_);
216 if (it != pool_map.end()) {
221 auto data = Create();
222 if (!data || !data->pool) {
226 auto const resource = std::make_shared<CommandPoolVK>(
227 std::move(data->pool), std::move(data->buffers), context_,
228 strong_context->GetDeviceHolder());
229 pool_map.emplace(context_hash_, resource);
233 g_all_pools_map[context_hash_][std::this_thread::get_id()] = resource;
240std::optional<CommandPoolRecyclerVK::RecycledData>
241CommandPoolRecyclerVK::Create() {
243 if (
auto data = Reuse()) {
248 auto context = context_.lock();
252 vk::CommandPoolCreateInfo info;
253 info.setQueueFamilyIndex(context->GetGraphicsQueue()->GetIndex().family);
254 info.setFlags(vk::CommandPoolCreateFlagBits::eTransient);
256 auto device = context->GetDevice();
257 auto [result, pool] =
device.createCommandPoolUnique(info);
258 if (result != vk::Result::eSuccess) {
261 return CommandPoolRecyclerVK::RecycledData{.pool = std::move(pool),
265std::optional<CommandPoolRecyclerVK::RecycledData>
266CommandPoolRecyclerVK::Reuse() {
268 Lock recycled_lock(recycled_mutex_);
269 if (recycled_.empty()) {
274 auto data = std::move(recycled_.back());
275 recycled_.pop_back();
276 return std::move(data);
280 vk::UniqueCommandPool&& pool,
281 std::vector<vk::UniqueCommandBuffer>&& buffers,
284 auto strong_context = context_.lock();
285 if (!strong_context) {
288 auto device = strong_context->GetDevice();
289 vk::CommandPoolResetFlags flags;
292 flags = vk::CommandPoolResetFlagBits::eReleaseResources;
294 const auto result =
device.resetCommandPool(pool.get(), flags);
295 if (result != vk::Result::eSuccess) {
296 VALIDATION_LOG <<
"Could not reset command pool: " << vk::to_string(result);
300 Lock recycled_lock(recycled_mutex_);
308 pool_map->erase(context_hash_);
313 auto found = g_all_pools_map.find(context_hash_);
314 if (found != g_all_pools_map.end()) {
315 found->second.erase(std::this_thread::get_id());
329 auto found = g_all_pools_map.find(context_hash_);
330 if (found != g_all_pools_map.end()) {
331 for (
auto& [thread_id, weak_pool] : found->second) {
332 auto pool = weak_pool.lock();
340 g_all_pools_map.erase(found);
BackgroundCommandPoolVK(BackgroundCommandPoolVK &&)=default
BackgroundCommandPoolVK(vk::UniqueCommandPool &&pool, std::vector< vk::UniqueCommandBuffer > &&buffers, size_t unused_count, std::weak_ptr< CommandPoolRecyclerVK > recycler)
static constexpr size_t kUnusedCommandBufferLimit
~BackgroundCommandPoolVK()
CommandPoolRecyclerVK(const std::shared_ptr< ContextVK > &context)
Creates a recycler for the given |ContextVK|.
void Dispose()
Clears this context's thread-local command pool.
static int GetGlobalPoolCount(const ContextVK &context)
std::shared_ptr< CommandPoolVK > Get()
Gets a command pool for the current thread.
void DestroyThreadLocalPools()
Clean up resources held by all per-thread command pools associated with the context.
void Reclaim(vk::UniqueCommandPool &&pool, std::vector< vk::UniqueCommandBuffer > &&buffers, bool should_trim=false)
Returns a command pool to be reset on a background thread.
void CollectCommandBuffer(vk::UniqueCommandBuffer &&buffer)
Collects the given |vk::CommandBuffer| to be retained.
vk::UniqueCommandBuffer CreateCommandBuffer()
Creates and returns a new |vk::CommandBuffer|.
A unique handle to a resource which will be reclaimed by the specified resource manager.
#define FML_DCHECK(condition)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
static Mutex g_all_pools_map_mutex
static thread_local std::unique_ptr< CommandPoolMap > tls_command_pool_map
std::unordered_map< uint64_t, std::shared_ptr< CommandPoolVK > > CommandPoolMap
A unique command pool and zero or more recycled command buffers.
vk::UniqueCommandPool pool
#define IPLR_GUARDED_BY(x)