| 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.
72 ~ResourceManagerVK();
73
74 private:
75 using Reclaimables = std::vector<std::unique_ptr<ResourceVK>>;
76
77 ResourceManagerVK();
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
165 ~UniqueResourceVKT() { Reset(); }
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