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