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