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