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