• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ResourceVk:
7 //    Resource lifetime tracking in the Vulkan back-end.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_
12 
13 #include "libANGLE/renderer/vulkan/vk_utils.h"
14 
15 namespace rx
16 {
17 namespace vk
18 {
19 // Tracks how a resource is used by ANGLE and by a VkQueue. The reference count indicates the number
20 // of times a resource is retained by ANGLE. The serial indicates the most recent use of a resource
21 // in the VkQueue. The reference count and serial together can determine if a resource is currently
22 // in use.
23 struct ResourceUse
24 {
25     ResourceUse() = default;
26 
27     // The number of times a resource is retained by ANGLE.
28     uint32_t counter = 0;
29 
30     // The most recent time of use in a VkQueue.
31     Serial serial;
32 };
33 
34 class SharedResourceUse final : angle::NonCopyable
35 {
36   public:
SharedResourceUse()37     SharedResourceUse() : mUse(nullptr) {}
~SharedResourceUse()38     ~SharedResourceUse() { ASSERT(!valid()); }
SharedResourceUse(SharedResourceUse && rhs)39     SharedResourceUse(SharedResourceUse &&rhs) : mUse(rhs.mUse) { rhs.mUse = nullptr; }
40     SharedResourceUse &operator=(SharedResourceUse &&rhs)
41     {
42         std::swap(mUse, rhs.mUse);
43         return *this;
44     }
45 
valid()46     ANGLE_INLINE bool valid() const { return mUse != nullptr; }
47 
init()48     void init()
49     {
50         ASSERT(!mUse);
51         mUse = new ResourceUse;
52         mUse->counter++;
53     }
54 
55     // Specifically for use with command buffers that are used as one-offs.
updateSerialOneOff(Serial serial)56     void updateSerialOneOff(Serial serial) { mUse->serial = serial; }
57 
release()58     ANGLE_INLINE void release()
59     {
60         ASSERT(valid());
61         ASSERT(mUse->counter > 0);
62         if (--mUse->counter == 0)
63         {
64             delete mUse;
65         }
66         mUse = nullptr;
67     }
68 
releaseAndUpdateSerial(Serial serial)69     ANGLE_INLINE void releaseAndUpdateSerial(Serial serial)
70     {
71         ASSERT(valid());
72         ASSERT(mUse->counter > 0);
73         ASSERT(mUse->serial <= serial);
74         mUse->serial = serial;
75         release();
76     }
77 
set(const SharedResourceUse & rhs)78     ANGLE_INLINE void set(const SharedResourceUse &rhs)
79     {
80         ASSERT(rhs.valid());
81         ASSERT(!valid());
82         ASSERT(rhs.mUse->counter < std::numeric_limits<uint32_t>::max());
83         mUse = rhs.mUse;
84         mUse->counter++;
85     }
86 
87     // The base counter value for a live resource is "1". Any value greater than one indicates
88     // the resource is in use by a command buffer.
usedInRecordedCommands()89     ANGLE_INLINE bool usedInRecordedCommands() const
90     {
91         ASSERT(valid());
92         return mUse->counter > 1;
93     }
94 
usedInRunningCommands(Serial lastCompletedSerial)95     ANGLE_INLINE bool usedInRunningCommands(Serial lastCompletedSerial) const
96     {
97         ASSERT(valid());
98         return mUse->serial > lastCompletedSerial;
99     }
100 
isCurrentlyInUse(Serial lastCompletedSerial)101     ANGLE_INLINE bool isCurrentlyInUse(Serial lastCompletedSerial) const
102     {
103         return usedInRecordedCommands() || usedInRunningCommands(lastCompletedSerial);
104     }
105 
getSerial()106     ANGLE_INLINE Serial getSerial() const
107     {
108         ASSERT(valid());
109         return mUse->serial;
110     }
111 
112   private:
113     ResourceUse *mUse;
114 };
115 
116 class SharedGarbage
117 {
118   public:
119     SharedGarbage();
120     SharedGarbage(SharedGarbage &&other);
121     SharedGarbage(SharedResourceUse &&use, std::vector<GarbageObject> &&garbage);
122     ~SharedGarbage();
123     SharedGarbage &operator=(SharedGarbage &&rhs);
124 
125     bool destroyIfComplete(RendererVk *renderer, Serial completedSerial);
126 
127   private:
128     SharedResourceUse mLifetime;
129     std::vector<GarbageObject> mGarbage;
130 };
131 
132 using SharedGarbageList = std::vector<SharedGarbage>;
133 
134 // Mixin to abstract away the resource use tracking.
135 class ResourceUseList final : angle::NonCopyable
136 {
137   public:
138     ResourceUseList();
139     ResourceUseList(ResourceUseList &&other);
140     virtual ~ResourceUseList();
141     ResourceUseList &operator=(ResourceUseList &&rhs);
142 
143     void add(const SharedResourceUse &resourceUse);
144 
145     void releaseResourceUses();
146     void releaseResourceUsesAndUpdateSerials(Serial serial);
147 
empty()148     bool empty() { return mResourceUses.empty(); }
149 
150   private:
151     std::vector<SharedResourceUse> mResourceUses;
152 };
153 
add(const SharedResourceUse & resourceUse)154 ANGLE_INLINE void ResourceUseList::add(const SharedResourceUse &resourceUse)
155 {
156     SharedResourceUse newUse;
157     newUse.set(resourceUse);
158     mResourceUses.emplace_back(std::move(newUse));
159 }
160 
161 // This is a helper class for back-end objects used in Vk command buffers. They keep a record
162 // of their use in ANGLE and VkQueues via SharedResourceUse.
163 class Resource : angle::NonCopyable
164 {
165   public:
166     virtual ~Resource();
167 
168     // Returns true if the resource is used by ANGLE in an unflushed command buffer.
usedInRecordedCommands()169     bool usedInRecordedCommands() const { return mUse.usedInRecordedCommands(); }
170 
171     // Determine if the driver has finished execution with this resource.
usedInRunningCommands(Serial lastCompletedSerial)172     bool usedInRunningCommands(Serial lastCompletedSerial) const
173     {
174         return mUse.usedInRunningCommands(lastCompletedSerial);
175     }
176 
177     // Returns true if the resource is in use by ANGLE or the driver.
isCurrentlyInUse(Serial lastCompletedSerial)178     bool isCurrentlyInUse(Serial lastCompletedSerial) const
179     {
180         return mUse.isCurrentlyInUse(lastCompletedSerial);
181     }
182 
183     // Ensures the driver is caught up to this resource and it is only in use by ANGLE.
184     angle::Result finishRunningCommands(ContextVk *contextVk);
185 
186     // Complete all recorded and in-flight commands involving this resource
187     angle::Result waitForIdle(ContextVk *contextVk,
188                               const char *debugMessage,
189                               RenderPassClosureReason reason);
190 
191     // Adds the resource to a resource use list.
192     void retain(ResourceUseList *resourceUseList) const;
193 
194   protected:
195     Resource();
196     Resource(Resource &&other);
197     Resource &operator=(Resource &&rhs);
198 
199     // Current resource lifetime.
200     SharedResourceUse mUse;
201 };
202 
retain(ResourceUseList * resourceUseList)203 ANGLE_INLINE void Resource::retain(ResourceUseList *resourceUseList) const
204 {
205     // Store reference in resource list.
206     resourceUseList->add(mUse);
207 }
208 
209 // Similar to |Resource| above, this tracks object usage. This includes additional granularity to
210 // track whether an object is used for read-only or read/write access.
211 class ReadWriteResource : public angle::NonCopyable
212 {
213   public:
214     virtual ~ReadWriteResource();
215 
216     // Returns true if the resource is used by ANGLE in an unflushed command buffer.
usedInRecordedCommands()217     bool usedInRecordedCommands() const { return mReadOnlyUse.usedInRecordedCommands(); }
218 
219     // Determine if the driver has finished execution with this resource.
usedInRunningCommands(Serial lastCompletedSerial)220     bool usedInRunningCommands(Serial lastCompletedSerial) const
221     {
222         return mReadOnlyUse.usedInRunningCommands(lastCompletedSerial);
223     }
224 
225     // Returns true if the resource is in use by ANGLE or the driver.
isCurrentlyInUse(Serial lastCompletedSerial)226     bool isCurrentlyInUse(Serial lastCompletedSerial) const
227     {
228         return mReadOnlyUse.isCurrentlyInUse(lastCompletedSerial);
229     }
isCurrentlyInUseForWrite(Serial lastCompletedSerial)230     bool isCurrentlyInUseForWrite(Serial lastCompletedSerial) const
231     {
232         return mReadWriteUse.isCurrentlyInUse(lastCompletedSerial);
233     }
234 
235     // Ensures the driver is caught up to this resource and it is only in use by ANGLE.
236     angle::Result finishRunningCommands(ContextVk *contextVk);
237 
238     // Ensures the GPU write commands is completed.
239     angle::Result finishGPUWriteCommands(ContextVk *contextVk);
240 
241     // Complete all recorded and in-flight commands involving this resource
242     angle::Result waitForIdle(ContextVk *contextVk,
243                               const char *debugMessage,
244                               RenderPassClosureReason reason);
245 
246     // Adds the resource to a resource use list.
247     void retainReadOnly(ResourceUseList *resourceUseList) const;
248     void retainReadWrite(ResourceUseList *resourceUseList) const;
249 
250   protected:
251     ReadWriteResource();
252     ReadWriteResource(ReadWriteResource &&other);
253 
254     // Track any use of the object. Always updated on every retain call.
255     SharedResourceUse mReadOnlyUse;
256     // Track read/write use of the object. Only updated for retainReadWrite().
257     SharedResourceUse mReadWriteUse;
258 };
259 
retainReadOnly(ResourceUseList * resourceUseList)260 ANGLE_INLINE void ReadWriteResource::retainReadOnly(ResourceUseList *resourceUseList) const
261 {
262     // Store reference in resource list.
263     resourceUseList->add(mReadOnlyUse);
264 }
265 
retainReadWrite(ResourceUseList * resourceUseList)266 ANGLE_INLINE void ReadWriteResource::retainReadWrite(ResourceUseList *resourceUseList) const
267 {
268     // Store reference in resource list.
269     resourceUseList->add(mReadOnlyUse);
270     resourceUseList->add(mReadWriteUse);
271 }
272 
273 }  // namespace vk
274 }  // namespace rx
275 
276 #endif  // LIBANGLE_RENDERER_VULKAN_RESOURCEVK_H_
277