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 // Resource:
7 // Resource lifetime tracking in the Vulkan back-end.
8 //
9
10 #include "libANGLE/renderer/vulkan/ResourceVk.h"
11
12 #include "libANGLE/renderer/vulkan/ContextVk.h"
13
14 namespace rx
15 {
16 namespace vk
17 {
18 namespace
19 {
20 constexpr size_t kDefaultResourceUseCount = 4096;
21
FinishRunningCommands(ContextVk * contextVk,Serial serial)22 angle::Result FinishRunningCommands(ContextVk *contextVk, Serial serial)
23 {
24 return contextVk->finishToSerial(serial);
25 }
26
27 template <typename T>
WaitForIdle(ContextVk * contextVk,T * resource,const char * debugMessage,RenderPassClosureReason reason)28 angle::Result WaitForIdle(ContextVk *contextVk,
29 T *resource,
30 const char *debugMessage,
31 RenderPassClosureReason reason)
32 {
33 // If there are pending commands for the resource, flush them.
34 if (resource->usedInRecordedCommands())
35 {
36 ANGLE_TRY(contextVk->flushImpl(nullptr, reason));
37 }
38
39 // Make sure the driver is done with the resource.
40 if (resource->usedInRunningCommands(contextVk->getLastCompletedQueueSerial()))
41 {
42 if (debugMessage)
43 {
44 ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH, "%s", debugMessage);
45 }
46 ANGLE_TRY(resource->finishRunningCommands(contextVk));
47 }
48
49 ASSERT(!resource->isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()));
50
51 return angle::Result::Continue;
52 }
53 } // namespace
54
55 // Resource implementation.
Resource()56 Resource::Resource()
57 {
58 mUse.init();
59 }
60
Resource(Resource && other)61 Resource::Resource(Resource &&other) : Resource()
62 {
63 mUse = std::move(other.mUse);
64 }
65
operator =(Resource && rhs)66 Resource &Resource::operator=(Resource &&rhs)
67 {
68 std::swap(mUse, rhs.mUse);
69 return *this;
70 }
71
~Resource()72 Resource::~Resource()
73 {
74 mUse.release();
75 }
76
finishRunningCommands(ContextVk * contextVk)77 angle::Result Resource::finishRunningCommands(ContextVk *contextVk)
78 {
79 return FinishRunningCommands(contextVk, mUse.getSerial());
80 }
81
waitForIdle(ContextVk * contextVk,const char * debugMessage,RenderPassClosureReason reason)82 angle::Result Resource::waitForIdle(ContextVk *contextVk,
83 const char *debugMessage,
84 RenderPassClosureReason reason)
85 {
86 return WaitForIdle(contextVk, this, debugMessage, reason);
87 }
88
89 // Resource implementation.
ReadWriteResource()90 ReadWriteResource::ReadWriteResource()
91 {
92 mReadOnlyUse.init();
93 mReadWriteUse.init();
94 }
95
ReadWriteResource(ReadWriteResource && other)96 ReadWriteResource::ReadWriteResource(ReadWriteResource &&other) : ReadWriteResource()
97 {
98 *this = std::move(other);
99 }
100
~ReadWriteResource()101 ReadWriteResource::~ReadWriteResource()
102 {
103 mReadOnlyUse.release();
104 mReadWriteUse.release();
105 }
106
operator =(ReadWriteResource && other)107 ReadWriteResource &ReadWriteResource::operator=(ReadWriteResource &&other)
108 {
109 mReadOnlyUse = std::move(other.mReadOnlyUse);
110 mReadWriteUse = std::move(other.mReadWriteUse);
111 return *this;
112 }
113
finishRunningCommands(ContextVk * contextVk)114 angle::Result ReadWriteResource::finishRunningCommands(ContextVk *contextVk)
115 {
116 ASSERT(!mReadOnlyUse.usedInRecordedCommands());
117 return FinishRunningCommands(contextVk, mReadOnlyUse.getSerial());
118 }
119
finishGPUWriteCommands(ContextVk * contextVk)120 angle::Result ReadWriteResource::finishGPUWriteCommands(ContextVk *contextVk)
121 {
122 ASSERT(!mReadWriteUse.usedInRecordedCommands());
123 return FinishRunningCommands(contextVk, mReadWriteUse.getSerial());
124 }
125
waitForIdle(ContextVk * contextVk,const char * debugMessage,RenderPassClosureReason reason)126 angle::Result ReadWriteResource::waitForIdle(ContextVk *contextVk,
127 const char *debugMessage,
128 RenderPassClosureReason reason)
129 {
130 return WaitForIdle(contextVk, this, debugMessage, reason);
131 }
132
133 // SharedBufferSuballocationGarbage implementation.
destroyIfComplete(RendererVk * renderer,Serial completedSerial)134 bool SharedBufferSuballocationGarbage::destroyIfComplete(RendererVk *renderer,
135 Serial completedSerial)
136 {
137 if (mLifetime.isCurrentlyInUse(completedSerial))
138 {
139 return false;
140 }
141
142 mBuffer.destroy(renderer->getDevice());
143 mSuballocation.destroy(renderer);
144 mLifetime.release();
145 return true;
146 }
147
148 // SharedGarbage implementation.
149 SharedGarbage::SharedGarbage() = default;
150
SharedGarbage(SharedGarbage && other)151 SharedGarbage::SharedGarbage(SharedGarbage &&other)
152 {
153 *this = std::move(other);
154 }
155
SharedGarbage(SharedResourceUse && use,std::vector<GarbageObject> && garbage)156 SharedGarbage::SharedGarbage(SharedResourceUse &&use, std::vector<GarbageObject> &&garbage)
157 : mLifetime(std::move(use)), mGarbage(std::move(garbage))
158 {}
159
160 SharedGarbage::~SharedGarbage() = default;
161
operator =(SharedGarbage && rhs)162 SharedGarbage &SharedGarbage::operator=(SharedGarbage &&rhs)
163 {
164 std::swap(mLifetime, rhs.mLifetime);
165 std::swap(mGarbage, rhs.mGarbage);
166 return *this;
167 }
168
destroyIfComplete(RendererVk * renderer,Serial completedSerial)169 bool SharedGarbage::destroyIfComplete(RendererVk *renderer, Serial completedSerial)
170 {
171 if (mLifetime.isCurrentlyInUse(completedSerial))
172 {
173 return false;
174 }
175
176 for (GarbageObject &object : mGarbage)
177 {
178 object.destroy(renderer);
179 }
180
181 mLifetime.release();
182
183 return true;
184 }
185
186 // ResourceUseList implementation.
ResourceUseList()187 ResourceUseList::ResourceUseList()
188 {
189 mResourceUses.reserve(kDefaultResourceUseCount);
190 }
191
ResourceUseList(ResourceUseList && other)192 ResourceUseList::ResourceUseList(ResourceUseList &&other)
193 {
194 *this = std::move(other);
195 other.mResourceUses.reserve(kDefaultResourceUseCount);
196 }
197
~ResourceUseList()198 ResourceUseList::~ResourceUseList()
199 {
200 ASSERT(mResourceUses.empty());
201 }
202
operator =(ResourceUseList && rhs)203 ResourceUseList &ResourceUseList::operator=(ResourceUseList &&rhs)
204 {
205 std::swap(mResourceUses, rhs.mResourceUses);
206 return *this;
207 }
208
releaseResourceUses()209 void ResourceUseList::releaseResourceUses()
210 {
211 for (SharedResourceUse &use : mResourceUses)
212 {
213 use.release();
214 }
215
216 mResourceUses.clear();
217 }
218
releaseResourceUsesAndUpdateSerials(Serial serial)219 void ResourceUseList::releaseResourceUsesAndUpdateSerials(Serial serial)
220 {
221 for (SharedResourceUse &use : mResourceUses)
222 {
223 use.releaseAndUpdateSerial(serial);
224 }
225
226 mResourceUses.clear();
227 }
228 } // namespace vk
229 } // namespace rx
230