1 /*
2 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #include "src/gpu/ganesh/GrRenderTask.h"
8
9 #include "include/core/SkRect.h"
10 #include "include/core/SkString.h"
11 #include "include/core/SkTypes.h"
12 #include "src/gpu/ganesh/GrDrawingManager.h"
13 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
14 #include "src/gpu/ganesh/GrSurface.h"
15 #include "src/gpu/ganesh/GrSurfaceProxy.h"
16 #include "src/gpu/ganesh/GrTextureProxy.h"
17 #include "src/gpu/ganesh/GrTextureProxyPriv.h"
18 #include "src/gpu/ganesh/GrTextureResolveManager.h"
19 #include "src/gpu/ganesh/GrTextureResolveRenderTask.h"
20
21 #include <algorithm>
22 #include <atomic>
23 #include <utility>
24
CreateUniqueID()25 uint32_t GrRenderTask::CreateUniqueID() {
26 static std::atomic<uint32_t> nextID{1};
27 uint32_t id;
28 do {
29 id = nextID.fetch_add(1, std::memory_order_relaxed);
30 } while (id == SK_InvalidUniqueID);
31 return id;
32 }
33
GrRenderTask()34 GrRenderTask::GrRenderTask()
35 : fUniqueID(CreateUniqueID())
36 , fFlags(0) {
37 }
38
disown(GrDrawingManager * drawingMgr)39 void GrRenderTask::disown(GrDrawingManager* drawingMgr) {
40 SkASSERT(!fDrawingMgr || drawingMgr == fDrawingMgr);
41 SkASSERT(this->isClosed());
42 if (this->isSetFlag(kDisowned_Flag)) {
43 return;
44 }
45 SkDEBUGCODE(fDrawingMgr = nullptr);
46 this->setFlag(kDisowned_Flag);
47
48 for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
49 if (this == drawingMgr->getLastRenderTask(target.get())) {
50 drawingMgr->setLastRenderTask(target.get(), nullptr);
51 }
52 }
53 }
54
makeSkippable()55 void GrRenderTask::makeSkippable() {
56 SkASSERT(this->isClosed());
57 if (!this->isSkippable()) {
58 this->setFlag(kSkippable_Flag);
59 this->onMakeSkippable();
60 }
61 }
62
63 #ifdef SK_DEBUG
~GrRenderTask()64 GrRenderTask::~GrRenderTask() {
65 SkASSERT(this->isSetFlag(kDisowned_Flag));
66 }
67
deferredProxiesAreInstantiated() const68 bool GrRenderTask::deferredProxiesAreInstantiated() const {
69 for (int i = 0; i < fDeferredProxies.size(); ++i) {
70 if (!fDeferredProxies[i]->isInstantiated()) {
71 return false;
72 }
73 }
74
75 return true;
76 }
77 #endif
78
makeClosed(GrRecordingContext * rContext)79 void GrRenderTask::makeClosed(GrRecordingContext* rContext) {
80 if (this->isClosed()) {
81 return;
82 }
83
84 SkIRect targetUpdateBounds;
85 if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(rContext, &targetUpdateBounds)) {
86 GrSurfaceProxy* proxy = this->target(0);
87 if (proxy->requiresManualMSAAResolve()) {
88 SkASSERT(this->target(0)->asRenderTargetProxy());
89 this->target(0)->asRenderTargetProxy()->markMSAADirty(targetUpdateBounds);
90 }
91 GrTextureProxy* textureProxy = this->target(0)->asTextureProxy();
92 if (textureProxy && skgpu::Mipmapped::kYes == textureProxy->mipmapped()) {
93 textureProxy->markMipmapsDirty();
94 }
95 }
96
97 if (fTextureResolveTask) {
98 this->addDependency(fTextureResolveTask);
99 fTextureResolveTask->makeClosed(rContext);
100 fTextureResolveTask = nullptr;
101 }
102
103 this->setFlag(kClosed_Flag);
104 }
105
prepare(GrOpFlushState * flushState)106 void GrRenderTask::prepare(GrOpFlushState* flushState) {
107 for (int i = 0; i < fDeferredProxies.size(); ++i) {
108 fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
109 }
110
111 this->onPrepare(flushState);
112 }
113
114 // Add a GrRenderTask-based dependency
addDependency(GrRenderTask * dependedOn)115 void GrRenderTask::addDependency(GrRenderTask* dependedOn) {
116 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
117 SkASSERT(!this->dependsOn(dependedOn)); // caller should weed out duplicates
118
119 fDependencies.push_back(dependedOn);
120 dependedOn->addDependent(this);
121
122 SkDEBUGCODE(this->validate());
123 }
124
addDependenciesFromOtherTask(GrRenderTask * otherTask)125 void GrRenderTask::addDependenciesFromOtherTask(GrRenderTask* otherTask) {
126 SkASSERT(otherTask);
127 for (GrRenderTask* task : otherTask->fDependencies) {
128 // The task should not be adding a dependency to itself.
129 SkASSERT(task != this);
130 if (!this->dependsOn(task)) {
131 this->addDependency(task);
132 }
133 }
134 }
135
136 // Convert from a GrSurface-based dependency to a GrRenderTask one
addDependency(GrDrawingManager * drawingMgr,GrSurfaceProxy * dependedOn,skgpu::Mipmapped mipmapped,GrTextureResolveManager textureResolveManager,const GrCaps & caps)137 void GrRenderTask::addDependency(GrDrawingManager* drawingMgr,
138 GrSurfaceProxy* dependedOn,
139 skgpu::Mipmapped mipmapped,
140 GrTextureResolveManager textureResolveManager,
141 const GrCaps& caps) {
142 // If it is still receiving dependencies, this GrRenderTask shouldn't be closed
143 SkASSERT(!this->isClosed());
144
145 GrRenderTask* dependedOnTask = drawingMgr->getLastRenderTask(dependedOn);
146
147 if (dependedOnTask == this) {
148 // self-read - presumably for dst reads. We don't need to do anything in this case. The
149 // XferProcessor will detect what is happening and insert a texture barrier.
150 SkASSERT(skgpu::Mipmapped::kNo == mipmapped);
151 // We should never attempt a self-read on a surface that has a separate MSAA renderbuffer.
152 SkASSERT(!dependedOn->requiresManualMSAAResolve());
153 SkASSERT(!dependedOn->asTextureProxy() ||
154 !dependedOn->asTextureProxy()->texPriv().isDeferred());
155 return;
156 }
157
158 bool alreadyDependent = false;
159 if (dependedOnTask) {
160 if (this->dependsOn(dependedOnTask) || fTextureResolveTask == dependedOnTask) {
161 alreadyDependent = true;
162 dependedOnTask = nullptr; // don't add duplicate dependencies
163 } else if (!dependedOnTask->isSetFlag(kAtlas_Flag)) {
164 // We are closing 'dependedOnTask' here bc the current contents of it are what 'this'
165 // renderTask depends on. We need a break in 'dependedOnTask' so that the usage of
166 // that state has a chance to execute.
167 dependedOnTask->makeClosed(drawingMgr->getContext());
168 }
169 }
170
171 auto resolveFlags = GrSurfaceProxy::ResolveFlags::kNone;
172
173 if (dependedOn->requiresManualMSAAResolve()) {
174 auto* renderTargetProxy = dependedOn->asRenderTargetProxy();
175 SkASSERT(renderTargetProxy);
176 if (renderTargetProxy->isMSAADirty()) {
177 resolveFlags |= GrSurfaceProxy::ResolveFlags::kMSAA;
178 }
179 }
180
181 GrTextureProxy* textureProxy = dependedOn->asTextureProxy();
182 if (skgpu::Mipmapped::kYes == mipmapped) {
183 SkASSERT(textureProxy);
184 if (skgpu::Mipmapped::kYes != textureProxy->mipmapped()) {
185 // There are some cases where we might be given a non-mipmapped texture with a mipmap
186 // filter. See skbug.com/7094.
187 mipmapped = skgpu::Mipmapped::kNo;
188 } else if (textureProxy->mipmapsAreDirty()) {
189 resolveFlags |= GrSurfaceProxy::ResolveFlags::kMipMaps;
190 }
191 }
192
193 // Does this proxy have msaa to resolve and/or mipmaps to regenerate?
194 if (GrSurfaceProxy::ResolveFlags::kNone != resolveFlags) {
195 if (!fTextureResolveTask) {
196 fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps);
197 }
198 fTextureResolveTask->addProxy(drawingMgr, sk_ref_sp(dependedOn), resolveFlags, caps);
199
200 // addProxy() should have closed the texture proxy's previous task.
201 SkASSERT(!dependedOnTask || dependedOnTask->isClosed());
202 SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
203
204 #ifdef SK_DEBUG
205 // addProxy() should have called addDependency (in this instance, recursively) on
206 // fTextureResolveTask.
207 if (dependedOnTask) {
208 SkASSERT(fTextureResolveTask->dependsOn(dependedOnTask));
209 }
210 if (textureProxy && textureProxy->texPriv().isDeferred()) {
211 SkASSERT(fTextureResolveTask->fDeferredProxies.back() == textureProxy);
212 }
213
214 // The GrTextureResolveRenderTask factory should have also marked the proxy clean, set the
215 // last renderTask on the textureProxy to textureResolveTask, and closed textureResolveTask.
216 if (resolveFlags & GrSurfaceProxy::ResolveFlags::kMSAA) {
217 if (GrRenderTargetProxy* renderTargetProxy = dependedOn->asRenderTargetProxy()) {
218 SkASSERT(!renderTargetProxy->isMSAADirty());
219 }
220 }
221 if (textureProxy && (resolveFlags & GrSurfaceProxy::ResolveFlags::kMipMaps)) {
222 SkASSERT(!textureProxy->mipmapsAreDirty());
223 }
224 SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
225 #endif
226 return;
227 }
228
229 if (textureProxy && textureProxy->texPriv().isDeferred()) {
230 if (alreadyDependent) {
231 SkASSERT(std::find(fDeferredProxies.begin(), fDeferredProxies.end(), textureProxy) !=
232 fDeferredProxies.end());
233 } else {
234 fDeferredProxies.push_back(textureProxy);
235 }
236 }
237
238 if (dependedOnTask) {
239 this->addDependency(dependedOnTask);
240 }
241 }
242
replaceDependency(const GrRenderTask * toReplace,GrRenderTask * replaceWith)243 void GrRenderTask::replaceDependency(const GrRenderTask* toReplace, GrRenderTask* replaceWith) {
244 for (auto& target : fDependencies) {
245 if (target == toReplace) {
246 target = replaceWith;
247 replaceWith->fDependents.push_back(this);
248 break;
249 }
250 }
251 }
252
replaceDependent(const GrRenderTask * toReplace,GrRenderTask * replaceWith)253 void GrRenderTask::replaceDependent(const GrRenderTask* toReplace, GrRenderTask* replaceWith) {
254 for (auto& target : fDependents) {
255 if (target == toReplace) {
256 target = replaceWith;
257 replaceWith->fDependencies.push_back(this);
258 break;
259 }
260 }
261 }
262
dependsOn(const GrRenderTask * dependedOn) const263 bool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const {
264 for (int i = 0; i < fDependencies.size(); ++i) {
265 if (fDependencies[i] == dependedOn) {
266 return true;
267 }
268 }
269
270 return false;
271 }
272
273
addDependent(GrRenderTask * dependent)274 void GrRenderTask::addDependent(GrRenderTask* dependent) {
275 fDependents.push_back(dependent);
276 }
277
278 #ifdef SK_DEBUG
isDependent(const GrRenderTask * dependent) const279 bool GrRenderTask::isDependent(const GrRenderTask* dependent) const {
280 for (int i = 0; i < fDependents.size(); ++i) {
281 if (fDependents[i] == dependent) {
282 return true;
283 }
284 }
285
286 return false;
287 }
288
validate() const289 void GrRenderTask::validate() const {
290 // TODO: check for loops and duplicates
291
292 for (int i = 0; i < fDependencies.size(); ++i) {
293 SkASSERT(fDependencies[i]->isDependent(this));
294 }
295 }
296 #endif
297
isInstantiated() const298 bool GrRenderTask::isInstantiated() const {
299 for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
300 GrSurfaceProxy* proxy = target.get();
301 if (!proxy->isInstantiated()) {
302 return false;
303 }
304
305 GrSurface* surface = proxy->peekSurface();
306 if (surface->wasDestroyed()) {
307 return false;
308 }
309 }
310
311 return true;
312 }
313
addTarget(GrDrawingManager * drawingMgr,sk_sp<GrSurfaceProxy> proxy)314 void GrRenderTask::addTarget(GrDrawingManager* drawingMgr, sk_sp<GrSurfaceProxy> proxy) {
315 SkASSERT(proxy);
316 SkASSERT(!this->isClosed());
317 SkASSERT(!fDrawingMgr || drawingMgr == fDrawingMgr);
318 SkDEBUGCODE(fDrawingMgr = drawingMgr);
319 drawingMgr->setLastRenderTask(proxy.get(), this);
320 proxy->isUsedAsTaskTarget();
321 fTargets.emplace_back(std::move(proxy));
322 }
323
324 #if defined(GPU_TEST_UTILS)
dump(const SkString & label,SkString indent,bool printDependencies,bool close) const325 void GrRenderTask::dump(const SkString& label,
326 SkString indent,
327 bool printDependencies,
328 bool close) const {
329 SkDebugf("%s%s --------------------------------------------------------------\n",
330 indent.c_str(),
331 label.c_str());
332 SkDebugf("%s%s task - renderTaskID: %u\n", indent.c_str(), this->name(), fUniqueID);
333
334 if (!fTargets.empty()) {
335 SkDebugf("%sTargets: \n", indent.c_str());
336 for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
337 SkASSERT(target);
338 SkString proxyStr = target->dump();
339 SkDebugf("%s%s\n", indent.c_str(), proxyStr.c_str());
340 }
341 }
342
343 if (printDependencies) {
344 SkDebugf("%sI rely On (%d): ", indent.c_str(), fDependencies.size());
345 for (int i = 0; i < fDependencies.size(); ++i) {
346 SkDebugf("%u, ", fDependencies[i]->fUniqueID);
347 }
348 SkDebugf("\n");
349
350 SkDebugf("%s(%d) Rely On Me: ", indent.c_str(), fDependents.size());
351 for (int i = 0; i < fDependents.size(); ++i) {
352 SkDebugf("%u, ", fDependents[i]->fUniqueID);
353 }
354 SkDebugf("\n");
355 }
356
357 if (close) {
358 SkDebugf("%s--------------------------------------------------------------\n\n",
359 indent.c_str());
360 }
361 }
362 #endif
363