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