| Flutter Impeller |

Classes | Public Member Functions | Static Public Member Functions | List of all members
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< CommandPoolVK > | Get ()
| 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] | context | The 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 }
impeller::g_all_pools_map_mutex
static Mutex g_all_pools_map_mutex
Definition: command_pool_vk.cc:172
impeller::tls_command_pool_map
static thread_local std::unique_ptr< CommandPoolMap > tls_command_pool_map
Definition: command_pool_vk.cc:168

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 }
impeller::CommandPoolMap
std::unordered_map< uint64_t, std::shared_ptr< CommandPoolVK > > CommandPoolMap
Definition: command_pool_vk.cc:158

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()) {
200 tls_command_pool_map.reset(new CommandPoolMap());
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 }
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67

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] | pool | The pool to recycle.
  [in] | should_trim | whether 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:

- impeller/renderer/backend/vulkan/command_pool_vk.h
- impeller/renderer/backend/vulkan/command_pool_vk.cc