Flutter Impeller
resource_manager_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_RESOURCE_MANAGER_VK_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_RESOURCE_MANAGER_VK_H_
7 
8 #include <condition_variable>
9 #include <memory>
10 #include <mutex>
11 #include <thread>
12 #include <vector>
13 
14 #include "flutter/fml/macros.h"
15 
16 namespace impeller {
17 
18 //------------------------------------------------------------------------------
19 /// @brief A resource that may be reclaimed by a |ResourceManagerVK|.
20 ///
21 /// To create a resource, use `UniqueResourceVKT` to create a unique handle:
22 ///
23 /// auto resource = UniqueResourceVKT<SomeResource>(resource_manager);
24 ///
25 /// @see |ResourceManagerVK::Reclaim|.
26 class ResourceVK {
27  public:
28  virtual ~ResourceVK() = default;
29 };
30 
31 //------------------------------------------------------------------------------
32 /// @brief A resource manager controls how resources are allocated and
33 /// reclaimed.
34 ///
35 /// Reclaimed resources are collected in a batch on a separate
36 /// thread. In the future, the resource manager may allow resource
37 /// pooling/reuse, delaying reclamation past frame workloads, etc...
38 ///
39 class ResourceManagerVK final
40  : public std::enable_shared_from_this<ResourceManagerVK> {
41  public:
42  //----------------------------------------------------------------------------
43  /// @brief Creates a shared resource manager (a dedicated thread).
44  ///
45  /// Upon creation, a thread is spawned which will collect resources as they
46  /// are reclaimed (passed to `Reclaim`). The thread will exit when the
47  /// resource manager is destroyed.
48  ///
49  /// @note Only one |ResourceManagerVK| should be created per Vulkan
50  /// context, but that contract is not enforced by this method.
51  ///
52  /// @return A resource manager if one could be created.
53  ///
54  static std::shared_ptr<ResourceManagerVK> Create();
55 
56  //----------------------------------------------------------------------------
57  /// @brief Mark a resource as being reclaimable.
58  ///
59  /// The resource will be reset at some point in the future.
60  ///
61  /// @param[in] resource The resource to reclaim.
62  ///
63  /// @note Despite being a public API, this method cannot be invoked
64  /// directly. Instead, use `UniqueResourceVKT` to create a unique
65  /// handle to a resource, which will call this method.
66  void Reclaim(std::unique_ptr<ResourceVK> resource);
67 
68  //----------------------------------------------------------------------------
69  /// @brief Destroys the resource manager.
70  ///
71  /// The resource manager will stop collecting resources and will be destroyed
72  /// when all references to it are dropped.
74 
75  private:
76  using Reclaimables = std::vector<std::unique_ptr<ResourceVK>>;
77 
79  std::mutex reclaimables_mutex_;
80  std::condition_variable reclaimables_cv_;
81  Reclaimables reclaimables_;
82  bool should_exit_ = false;
83  // This should be initialized last since it references the other instance
84  // variables.
85  std::thread waiter_;
86 
87  //----------------------------------------------------------------------------
88  /// @brief Starts the resource manager thread.
89  ///
90  /// This method is called implicitly by `Create`.
91  void Start();
92 
93  //----------------------------------------------------------------------------
94  /// @brief Terminates the resource manager thread.
95  ///
96  /// Any resources given to the resource manager post termination will be
97  /// collected when the resource manager is collected.
98  void Terminate();
99 
100  ResourceManagerVK(const ResourceManagerVK&) = delete;
101 
102  ResourceManagerVK& operator=(const ResourceManagerVK&) = delete;
103 };
104 
105 //------------------------------------------------------------------------------
106 /// @brief An internal type that is used to move a resource reference.
107 ///
108 /// Do not use directly, use `UniqueResourceVKT` instead.
109 ///
110 /// @tparam ResourceType_ The type of the resource.
111 ///
112 /// @see |UniqueResourceVKT|.
113 template <class ResourceType_>
114 class ResourceVKT : public ResourceVK {
115  public:
116  using ResourceType = ResourceType_;
117 
118  /// @brief Construct a resource from a move-constructible resource.
119  ///
120  /// @param[in] resource The resource to move.
121  explicit ResourceVKT(ResourceType&& resource)
122  : resource_(std::move(resource)) {}
123 
124  /// @brief Returns a pointer to the resource.
125  const ResourceType* Get() const { return &resource_; }
126 
127  private:
128  // Prevents subclassing, use `UniqueResourceVKT`.
129  ResourceVKT() = default;
130 
131  ResourceType resource_;
132 
133  ResourceVKT(const ResourceVKT&) = delete;
134 
135  ResourceVKT& operator=(const ResourceVKT&) = delete;
136 };
137 
138 //------------------------------------------------------------------------------
139 /// @brief A unique handle to a resource which will be reclaimed by the
140 /// specified resource manager.
141 ///
142 /// @tparam ResourceType_ A move-constructible resource type.
143 ///
144 template <class ResourceType_>
145 class UniqueResourceVKT final {
146  public:
147  using ResourceType = ResourceType_;
148 
149  /// @brief Construct a unique resource handle belonging to a manager.
150  ///
151  /// Initially the handle is empty, and can be populated by calling `Swap`.
152  ///
153  /// @param[in] resource_manager The resource manager.
154  explicit UniqueResourceVKT(std::weak_ptr<ResourceManagerVK> resource_manager)
155  : resource_manager_(std::move(resource_manager)) {}
156 
157  /// @brief Construct a unique resource handle belonging to a manager.
158  ///
159  /// Initially the handle is populated with the specified resource, but can
160  /// be replaced (reclaiming the old resource) by calling `Swap`.
161  ///
162  /// @param[in] resource_manager The resource manager.
163  /// @param[in] resource The resource to move.
164  explicit UniqueResourceVKT(std::weak_ptr<ResourceManagerVK> resource_manager,
165  ResourceType&& resource)
166  : resource_manager_(std::move(resource_manager)),
167  resource_(
168  std::make_unique<ResourceVKT<ResourceType>>(std::move(resource))) {}
169 
171 
172  /// @brief Returns a pointer to the resource.
173  const ResourceType* operator->() const {
174  // If this would segfault, fail with a nicer error message.
175  FML_CHECK(resource_) << "UniqueResourceVKT was reclaimed.";
176 
177  return resource_.get()->Get();
178  }
179 
180  /// @brief Reclaims the existing resource, if any, and replaces it.
181  ///
182  /// @param[in] other The (new) resource to move.
183  void Swap(ResourceType&& other) {
184  Reset();
185  resource_ = std::make_unique<ResourceVKT<ResourceType>>(std::move(other));
186  }
187 
188  /// @brief Reclaims the existing resource, if any.
189  void Reset() {
190  if (!resource_) {
191  return;
192  }
193  // If there is a manager, ask it to reclaim the resource. If there isn't a
194  // manager (because the manager has been destroyed), just drop it on the
195  // floor here.
196  if (auto manager = resource_manager_.lock()) {
197  manager->Reclaim(std::move(resource_));
198  }
199  resource_.reset();
200  }
201 
202  private:
203  std::weak_ptr<ResourceManagerVK> resource_manager_;
204  std::unique_ptr<ResourceVKT<ResourceType>> resource_;
205 
206  UniqueResourceVKT(const UniqueResourceVKT&) = delete;
207 
208  UniqueResourceVKT& operator=(const UniqueResourceVKT&) = delete;
209 };
210 
211 } // namespace impeller
212 
213 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_RESOURCE_MANAGER_VK_H_
impeller::ResourceManagerVK::Create
static std::shared_ptr< ResourceManagerVK > Create()
Creates a shared resource manager (a dedicated thread).
Definition: resource_manager_vk.cc:14
impeller::ResourceManagerVK
A resource manager controls how resources are allocated and reclaimed.
Definition: resource_manager_vk.h:39
impeller::UniqueResourceVKT
A unique handle to a resource which will be reclaimed by the specified resource manager.
Definition: resource_manager_vk.h:145
impeller::ResourceVKT
An internal type that is used to move a resource reference.
Definition: resource_manager_vk.h:114
impeller::UniqueResourceVKT::Swap
void Swap(ResourceType &&other)
Reclaims the existing resource, if any, and replaces it.
Definition: resource_manager_vk.h:183
impeller::ResourceVKT::ResourceType
ResourceType_ ResourceType
Definition: resource_manager_vk.h:116
impeller::ResourceManagerVK::Reclaim
void Reclaim(std::unique_ptr< ResourceVK > resource)
Mark a resource as being reclaimable.
Definition: resource_manager_vk.cc:75
impeller::ResourceVK
A resource that may be reclaimed by a |ResourceManagerVK|.
Definition: resource_manager_vk.h:26
impeller::ResourceVKT::Get
const ResourceType * Get() const
Returns a pointer to the resource.
Definition: resource_manager_vk.h:125
impeller::UniqueResourceVKT::~UniqueResourceVKT
~UniqueResourceVKT()
Definition: resource_manager_vk.h:170
impeller::UniqueResourceVKT::UniqueResourceVKT
UniqueResourceVKT(std::weak_ptr< ResourceManagerVK > resource_manager)
Construct a unique resource handle belonging to a manager.
Definition: resource_manager_vk.h:154
impeller::ResourceVKT::ResourceVKT
ResourceVKT(ResourceType &&resource)
Construct a resource from a move-constructible resource.
Definition: resource_manager_vk.h:121
impeller::UniqueResourceVKT::operator->
const ResourceType * operator->() const
Returns a pointer to the resource.
Definition: resource_manager_vk.h:173
impeller::ResourceVK::~ResourceVK
virtual ~ResourceVK()=default
std
Definition: comparable.h:95
impeller::UniqueResourceVKT< ImageResource >::ResourceType
ImageResource ResourceType
Definition: resource_manager_vk.h:147
impeller::ResourceManagerVK::~ResourceManagerVK
~ResourceManagerVK()
Destroys the resource manager.
Definition: resource_manager_vk.cc:25
impeller::UniqueResourceVKT::UniqueResourceVKT
UniqueResourceVKT(std::weak_ptr< ResourceManagerVK > resource_manager, ResourceType &&resource)
Construct a unique resource handle belonging to a manager.
Definition: resource_manager_vk.h:164
impeller
Definition: aiks_blur_unittests.cc:20
impeller::UniqueResourceVKT::Reset
void Reset()
Reclaims the existing resource, if any.
Definition: resource_manager_vk.h:189