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