• 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 // 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