Flutter Impeller
impeller::CommandPoolRecyclerVK Class Referencefinal

Creates and manages the lifecycle of |vk::CommandPool| objects. More...

#include <command_pool_vk.h>

Inheritance diagram for impeller::CommandPoolRecyclerVK:

Classes

struct  RecycledData
 A unique command pool and zero or more recycled command buffers. More...
 

Public Member Functions

void DestroyThreadLocalPools ()
 Clean up resources held by all per-thread command pools associated with the context. More...
 
 CommandPoolRecyclerVK (const std::shared_ptr< ContextVK > &context)
 Creates a recycler for the given |ContextVK|. More...
 
std::shared_ptr< CommandPoolVKGet ()
 Gets a command pool for the current thread. More...
 
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. More...
 
void Dispose ()
 Clears this context's thread-local command pool. More...
 

Static Public Member Functions

static int GetGlobalPoolCount (const ContextVK &context)
 

Detailed Description

Creates and manages the lifecycle of |vk::CommandPool| objects.

A |vk::CommandPool| is expensive to create and reset. This class manages the lifecycle of |vk::CommandPool| objects by creating and recycling them; or in other words, a pool for command pools.

A single instance should be created per |ContextVK|.

Every "frame", a single |CommandPoolResourceVk| is made available for each thread that calls |Get|. After calling |Dispose|, the current thread's pool is moved to a background thread, reset, and made available for the next time |Get| is called and needs to create a command pool.

Commands in the command pool are not necessarily done executing when the pool is recycled, when all references are dropped to the pool, they are reset and returned to the pool of available pools.

Note
This class is thread-safe.
See also
|vk::CommandPoolResourceVk|
|ContextVK|
https://arm-software.github.io/vulkan_best_practice_for_mobile_developers/samples/performance/command_buffer_usage/command_buffer_usage_tutorial.html

Definition at line 103 of file command_pool_vk.h.

Constructor & Destructor Documentation

◆ CommandPoolRecyclerVK()

impeller::CommandPoolRecyclerVK::CommandPoolRecyclerVK ( const std::shared_ptr< ContextVK > &  context)
explicit

Creates a recycler for the given |ContextVK|.

Parameters
[in]contextThe context to create the recycler for.

Definition at line 179 of file command_pool_vk.cc.

181  : context_(context), context_hash_(context->GetHash()) {}

Member Function Documentation

◆ DestroyThreadLocalPools()

void impeller::CommandPoolRecyclerVK::DestroyThreadLocalPools ( )

Clean up resources held by all per-thread command pools associated with the context.

Definition at line 305 of file command_pool_vk.cc.

305  {
306  // Delete the context's entry in this thread's command pool map.
307  if (tls_command_pool_map.get()) {
308  tls_command_pool_map.get()->erase(context_hash_);
309  }
310 
311  // Destroy all other thread-local CommandPoolVK instances associated with
312  // this context.
313  Lock all_pools_lock(g_all_pools_map_mutex);
314  auto found = g_all_pools_map.find(context_hash_);
315  if (found != g_all_pools_map.end()) {
316  for (auto& [thread_id, weak_pool] : found->second) {
317  auto pool = weak_pool.lock();
318  if (!pool) {
319  continue;
320  }
321  // Delete all objects held by this pool. The destroyed pool will still
322  // remain in its thread's TLS map until that thread exits.
323  pool->Destroy();
324  }
325  g_all_pools_map.erase(found);
326  }
327 }
static Mutex g_all_pools_map_mutex
static thread_local std::unique_ptr< CommandPoolMap > tls_command_pool_map

References impeller::g_all_pools_map_mutex, and impeller::tls_command_pool_map.

◆ Dispose()

void impeller::CommandPoolRecyclerVK::Dispose ( )

Clears this context's thread-local command pool.

Definition at line 290 of file command_pool_vk.cc.

290  {
291  CommandPoolMap* pool_map = tls_command_pool_map.get();
292  if (pool_map) {
293  pool_map->erase(context_hash_);
294  }
295 
296  {
297  Lock all_pools_lock(g_all_pools_map_mutex);
298  auto found = g_all_pools_map.find(context_hash_);
299  if (found != g_all_pools_map.end()) {
300  found->second.erase(std::this_thread::get_id());
301  }
302  }
303 }
std::unordered_map< uint64_t, std::shared_ptr< CommandPoolVK > > CommandPoolMap

References impeller::g_all_pools_map_mutex, and impeller::tls_command_pool_map.

◆ Get()

std::shared_ptr< CommandPoolVK > impeller::CommandPoolRecyclerVK::Get ( )

Gets a command pool for the current thread.

Warning
Returns a |nullptr| if a pool could not be created.

Definition at line 192 of file command_pool_vk.cc.

192  {
193  auto const strong_context = context_.lock();
194  if (!strong_context) {
195  return nullptr;
196  }
197 
198  // If there is a resource in used for this thread and context, return it.
199  if (!tls_command_pool_map.get()) {
201  }
202  CommandPoolMap& pool_map = *tls_command_pool_map.get();
203  auto const it = pool_map.find(context_hash_);
204  if (it != pool_map.end()) {
205  return it->second;
206  }
207 
208  // Otherwise, create a new resource and return it.
209  auto data = Create();
210  if (!data || !data->pool) {
211  return nullptr;
212  }
213 
214  auto const resource = std::make_shared<CommandPoolVK>(
215  std::move(data->pool), std::move(data->buffers), context_);
216  pool_map.emplace(context_hash_, resource);
217 
218  {
219  Lock all_pools_lock(g_all_pools_map_mutex);
220  g_all_pools_map[context_hash_][std::this_thread::get_id()] = resource;
221  }
222 
223  return resource;
224 }
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:68

References data, impeller::g_all_pools_map_mutex, and impeller::tls_command_pool_map.

◆ GetGlobalPoolCount()

int impeller::CommandPoolRecyclerVK::GetGlobalPoolCount ( const ContextVK context)
static

Definition at line 185 of file command_pool_vk.cc.

185  {
186  Lock all_pools_lock(g_all_pools_map_mutex);
187  auto it = g_all_pools_map.find(context.GetHash());
188  return it != g_all_pools_map.end() ? it->second.size() : 0;
189 }

References impeller::g_all_pools_map_mutex, and impeller::ContextVK::GetHash().

Referenced by impeller::testing::TEST().

◆ Reclaim()

void impeller::CommandPoolRecyclerVK::Reclaim ( vk::UniqueCommandPool &&  pool,
std::vector< vk::UniqueCommandBuffer > &&  buffers,
bool  should_trim = false 
)

Returns a command pool to be reset on a background thread.

Parameters
[in]poolThe pool to recycle.
[in]should_trimwhether to trim command pool memory before reseting.

Definition at line 266 of file command_pool_vk.cc.

269  {
270  // Reset the pool on a background thread.
271  auto strong_context = context_.lock();
272  if (!strong_context) {
273  return;
274  }
275  auto device = strong_context->GetDevice();
276  if (should_trim) {
277  buffers.clear();
278  device.resetCommandPool(pool.get(),
279  vk::CommandPoolResetFlagBits::eReleaseResources);
280  } else {
281  device.resetCommandPool(pool.get(), {});
282  }
283 
284  // Move the pool to the recycled list.
285  Lock recycled_lock(recycled_mutex_);
286  recycled_.push_back(
287  RecycledData{.pool = std::move(pool), .buffers = std::move(buffers)});
288 }

References impeller::CommandPoolRecyclerVK::RecycledData::pool.


The documentation for this class was generated from the following files: