xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrRenderTask.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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