Flutter Impeller
command_pool_vk.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <memory>
8 #include <optional>
9 #include <utility>
10 #include "fml/macros.h"
11 #include "impeller/base/thread.h"
13 #include "impeller/renderer/backend/vulkan/vk.h" // IWYU pragma: keep.
14 
15 namespace impeller {
16 
17 class ContextVK;
18 class CommandPoolRecyclerVK;
19 
20 //------------------------------------------------------------------------------
21 /// @brief Manages the lifecycle of a single |vk::CommandPool|.
22 ///
23 /// A |vk::CommandPool| is expensive to create and reset. This class manages
24 /// the lifecycle of a single |vk::CommandPool| by returning to the origin
25 /// (|CommandPoolRecyclerVK|) when it is destroyed to be reused.
26 ///
27 /// @warning This class is not thread-safe.
28 ///
29 /// @see |CommandPoolRecyclerVK|
30 class CommandPoolVK final {
31  public:
33 
34  /// @brief Creates a resource that manages the life of a command pool.
35  ///
36  /// @param[in] pool The command pool to manage.
37  /// @param[in] recycler The context that will be notified on destruction.
38  explicit CommandPoolVK(vk::UniqueCommandPool pool,
39  std::weak_ptr<ContextVK>& context)
40  : pool_(std::move(pool)), context_(context) {}
41 
42  /// @brief Creates and returns a new |vk::CommandBuffer|.
43  ///
44  /// @return Always returns a new |vk::CommandBuffer|, but if for any
45  /// reason a valid command buffer could not be created, it will be
46  /// a `{}` default instance (i.e. while being torn down).
47  vk::UniqueCommandBuffer CreateCommandBuffer();
48 
49  /// @brief Collects the given |vk::CommandBuffer| to be retained.
50  ///
51  /// @param[in] buffer The |vk::CommandBuffer| to collect.
52  ///
53  /// @see |GarbageCollectBuffersIfAble|
54  void CollectCommandBuffer(vk::UniqueCommandBuffer&& buffer);
55 
56  /// @brief Delete all Vulkan objects in this command pool.
57  void Destroy();
58 
59  private:
60  FML_DISALLOW_COPY_AND_ASSIGN(CommandPoolVK);
61 
62  Mutex pool_mutex_;
63  vk::UniqueCommandPool pool_ IPLR_GUARDED_BY(pool_mutex_);
64  std::weak_ptr<ContextVK>& context_;
65 
66  // Used to retain a reference on these until the pool is reset.
67  std::vector<vk::UniqueCommandBuffer> collected_buffers_
68  IPLR_GUARDED_BY(pool_mutex_);
69 };
70 
71 //------------------------------------------------------------------------------
72 /// @brief Creates and manages the lifecycle of |vk::CommandPool| objects.
73 ///
74 /// A |vk::CommandPool| is expensive to create and reset. This class manages
75 /// the lifecycle of |vk::CommandPool| objects by creating and recycling them;
76 /// or in other words, a pool for command pools.
77 ///
78 /// A single instance should be created per |ContextVK|.
79 ///
80 /// Every "frame", a single |CommandPoolResourceVk| is made available for each
81 /// thread that calls |Get|. After calling |Dispose|, the current thread's pool
82 /// is moved to a background thread, reset, and made available for the next time
83 /// |Get| is called and needs to create a command pool.
84 ///
85 /// Commands in the command pool are not necessarily done executing when the
86 /// pool is recycled, when all references are dropped to the pool, they are
87 /// reset and returned to the pool of available pools.
88 ///
89 /// @note This class is thread-safe.
90 ///
91 /// @see |vk::CommandPoolResourceVk|
92 /// @see |ContextVK|
93 /// @see
94 /// https://arm-software.github.io/vulkan_best_practice_for_mobile_developers/samples/performance/command_buffer_usage/command_buffer_usage_tutorial.html
96  : public std::enable_shared_from_this<CommandPoolRecyclerVK> {
97  public:
99 
100  /// @brief Clean up resources held by all per-thread command pools
101  /// associated with the given context.
102  ///
103  /// @param[in] context The context.
104  static void DestroyThreadLocalPools(const ContextVK* context);
105 
106  /// @brief Creates a recycler for the given |ContextVK|.
107  ///
108  /// @param[in] context The context to create the recycler for.
109  explicit CommandPoolRecyclerVK(std::weak_ptr<ContextVK> context)
110  : context_(std::move(context)) {}
111 
112  /// @brief Gets a command pool for the current thread.
113  ///
114  /// @warning Returns a |nullptr| if a pool could not be created.
115  std::shared_ptr<CommandPoolVK> Get();
116 
117  /// @brief Returns a command pool to be reset on a background thread.
118  ///
119  /// @param[in] pool The pool to recycler.
120  void Reclaim(vk::UniqueCommandPool&& pool);
121 
122  /// @brief Clears all recycled command pools to let them be reclaimed.
123  void Dispose();
124 
125  private:
126  std::weak_ptr<ContextVK> context_;
127 
128  Mutex recycled_mutex_;
129  std::vector<vk::UniqueCommandPool> recycled_ IPLR_GUARDED_BY(recycled_mutex_);
130 
131  /// @brief Creates a new |vk::CommandPool|.
132  ///
133  /// @returns Returns a |std::nullopt| if a pool could not be created.
134  std::optional<vk::UniqueCommandPool> Create();
135 
136  /// @brief Reuses a recycled |vk::CommandPool|, if available.
137  ///
138  /// @returns Returns a |std::nullopt| if a pool was not available.
139  std::optional<vk::UniqueCommandPool> Reuse();
140 
141  FML_DISALLOW_COPY_AND_ASSIGN(CommandPoolRecyclerVK);
142 };
143 
144 } // namespace impeller
impeller::CommandPoolVK::~CommandPoolVK
~CommandPoolVK()
Definition: command_pool_vk.cc:61
impeller::CommandPoolRecyclerVK::DestroyThreadLocalPools
static void DestroyThreadLocalPools(const ContextVK *context)
Clean up resources held by all per-thread command pools associated with the given context.
Definition: command_pool_vk.cc:244
impeller::CommandPoolRecyclerVK::CommandPoolRecyclerVK
CommandPoolRecyclerVK(std::weak_ptr< ContextVK > context)
Creates a recycler for the given |ContextVK|.
Definition: command_pool_vk.h:109
vk.h
impeller::CommandPoolVK::CollectCommandBuffer
void CollectCommandBuffer(vk::UniqueCommandBuffer &&buffer)
Collects the given |vk::CommandBuffer| to be retained.
Definition: command_pool_vk.cc:108
impeller::CommandPoolVK
Manages the lifecycle of a single |vk::CommandPool|.
Definition: command_pool_vk.h:30
impeller::CommandPoolRecyclerVK::Get
std::shared_ptr< CommandPoolVK > Get()
Gets a command pool for the current thread.
Definition: command_pool_vk.cc:144
impeller::CommandPoolVK::Destroy
void Destroy()
Delete all Vulkan objects in this command pool.
Definition: command_pool_vk.cc:119
impeller::CommandPoolRecyclerVK::Reclaim
void Reclaim(vk::UniqueCommandPool &&pool)
Returns a command pool to be reset on a background thread.
Definition: command_pool_vk.cc:216
impeller::CommandPoolRecyclerVK::~CommandPoolRecyclerVK
~CommandPoolRecyclerVK()
Definition: command_pool_vk.cc:232
impeller::CommandPoolRecyclerVK::Dispose
void Dispose()
Clears all recycled command pools to let them be reclaimed.
Definition: command_pool_vk.cc:237
impeller::CommandPoolVK::CreateCommandBuffer
vk::UniqueCommandBuffer CreateCommandBuffer()
Creates and returns a new |vk::CommandBuffer|.
Definition: command_pool_vk.cc:85
impeller::ContextVK
Definition: context_vk.h:36
std
Definition: comparable.h:98
context_vk.h
impeller::CommandPoolVK::CommandPoolVK
CommandPoolVK(vk::UniqueCommandPool pool, std::weak_ptr< ContextVK > &context)
Creates a resource that manages the life of a command pool.
Definition: command_pool_vk.h:38
impeller::CommandPoolRecyclerVK
Creates and manages the lifecycle of |vk::CommandPool| objects.
Definition: command_pool_vk.h:95
thread.h
impeller
Definition: aiks_context.cc:10