| 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"
12 #include "impeller/renderer/backend/vulkan/context_vk.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:
32 ~CommandPoolVK();
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
95 class CommandPoolRecyclerVK final
96 : public std::enable_shared_from_this<CommandPoolRecyclerVK> {
97 public:
98 ~CommandPoolRecyclerVK();
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