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