Flutter Engine
 
Loading...
Searching...
No Matches
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.
 
 CommandPoolRecyclerVK (const std::shared_ptr< ContextVK > &context)
 Creates a recycler for the given |ContextVK|.
 
std::shared_ptr< CommandPoolVKGet ()
 Gets a command pool for the current thread.
 
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 Dispose ()
 Clears this context's thread-local command pool.
 

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 178 of file command_pool_vk.cc.

180 : 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 306 of file command_pool_vk.cc.

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

291 {
292 CommandPoolMap* pool_map = tls_command_pool_map.get();
293 if (pool_map) {
294 pool_map->erase(context_hash_);
295 }
296
297 {
298 Lock all_pools_lock(g_all_pools_map_mutex);
299 auto found = g_all_pools_map.find(context_hash_);
300 if (found != g_all_pools_map.end()) {
301 found->second.erase(std::this_thread::get_id());
302 }
303 }
304}
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 191 of file command_pool_vk.cc.

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

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 184 of file command_pool_vk.cc.

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

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 265 of file command_pool_vk.cc.

268 {
269 // Reset the pool on a background thread.
270 auto strong_context = context_.lock();
271 if (!strong_context) {
272 return;
273 }
274 auto device = strong_context->GetDevice();
275 vk::CommandPoolResetFlags flags;
276 if (should_trim) {
277 buffers.clear();
278 flags = vk::CommandPoolResetFlagBits::eReleaseResources;
279 }
280 const auto result = device.resetCommandPool(pool.get(), flags);
281 if (result != vk::Result::eSuccess) {
282 VALIDATION_LOG << "Could not reset command pool: " << vk::to_string(result);
283 }
284
285 // Move the pool to the recycled list.
286 Lock recycled_lock(recycled_mutex_);
287 recycled_.push_back(
288 RecycledData{.pool = std::move(pool), .buffers = std::move(buffers)});
289}
VkDevice device
Definition main.cc:69
#define VALIDATION_LOG
Definition validation.h:91

References device, impeller::CommandPoolRecyclerVK::RecycledData::pool, and VALIDATION_LOG.


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