blob: fece63f45b2f72fb02028b57f2f316c68eb442c1 [file] [log] [blame]
Chris Dalton6b498102019-08-01 14:14:52 -06001/*
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/GrRenderTargetPriv.h"
11#include "src/gpu/GrStencilAttachment.h"
12#include "src/gpu/GrTextureProxyPriv.h"
Chris Daltone2a903e2019-09-18 13:41:50 -060013#include "src/gpu/GrTextureResolveRenderTask.h"
Chris Dalton6b498102019-08-01 14:14:52 -060014
15uint32_t GrRenderTask::CreateUniqueID() {
16 static std::atomic<uint32_t> nextID{1};
17 uint32_t id;
18 do {
19 id = nextID++;
20 } while (id == SK_InvalidUniqueID);
21 return id;
22}
23
Greg Daniel16f5c652019-10-29 11:26:01 -040024GrRenderTask::GrRenderTask()
25 : fUniqueID(CreateUniqueID())
26 , fFlags(0) {
27}
28
Adlai Hollerd71b7b02020-06-08 15:55:00 -040029void GrRenderTask::disown(GrDrawingManager* drawingMgr) {
30 if (this->isSetFlag(kDisowned_Flag)) {
31 return;
Chris Dalton6b498102019-08-01 14:14:52 -060032 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -040033 this->setFlag(kDisowned_Flag);
Adlai Holler33d569e2020-06-16 14:30:08 -040034
35 for (const GrSurfaceProxyView& target : fTargets) {
36 if (this == drawingMgr->getLastRenderTask(target.proxy())) {
37 drawingMgr->setLastRenderTask(target.proxy(), nullptr);
38 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -040039 }
40}
41
Adlai Holler33d569e2020-06-16 14:30:08 -040042#ifdef SK_DEBUG
Adlai Hollerd71b7b02020-06-08 15:55:00 -040043GrRenderTask::~GrRenderTask() {
44 SkASSERT(this->isSetFlag(kDisowned_Flag));
Chris Dalton6b498102019-08-01 14:14:52 -060045}
46
Chris Dalton6b498102019-08-01 14:14:52 -060047bool GrRenderTask::deferredProxiesAreInstantiated() const {
48 for (int i = 0; i < fDeferredProxies.count(); ++i) {
49 if (!fDeferredProxies[i]->isInstantiated()) {
50 return false;
51 }
52 }
53
54 return true;
55}
56#endif
57
Chris Daltonaa3cbb82019-08-21 00:01:21 -060058void GrRenderTask::makeClosed(const GrCaps& caps) {
59 if (this->isClosed()) {
60 return;
61 }
62
Chris Dalton16a33c62019-09-24 22:19:17 -060063 SkIRect targetUpdateBounds;
64 if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) {
Adlai Holler33d569e2020-06-16 14:30:08 -040065 GrSurfaceProxy* proxy = this->target(0).proxy();
Greg Daniel16f5c652019-10-29 11:26:01 -040066 if (proxy->requiresManualMSAAResolve()) {
Adlai Holler33d569e2020-06-16 14:30:08 -040067 SkASSERT(this->target(0).asRenderTargetProxy());
68 this->target(0).asRenderTargetProxy()->markMSAADirty(targetUpdateBounds,
69 this->target(0).origin());
Chris Dalton4ece96d2019-08-30 11:26:39 -060070 }
Adlai Holler33d569e2020-06-16 14:30:08 -040071 GrTextureProxy* textureProxy = this->target(0).asTextureProxy();
Chris Daltonaa3cbb82019-08-21 00:01:21 -060072 if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
73 textureProxy->markMipMapsDirty();
74 }
75 }
76
Chris Daltone2a903e2019-09-18 13:41:50 -060077 if (fTextureResolveTask) {
78 this->addDependency(fTextureResolveTask);
79 fTextureResolveTask->makeClosed(caps);
80 fTextureResolveTask = nullptr;
81 }
82
Chris Daltonaa3cbb82019-08-21 00:01:21 -060083 this->setFlag(kClosed_Flag);
84}
85
Chris Dalton6b498102019-08-01 14:14:52 -060086void GrRenderTask::prepare(GrOpFlushState* flushState) {
87 for (int i = 0; i < fDeferredProxies.count(); ++i) {
88 fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
89 }
90
91 this->onPrepare(flushState);
92}
93
94// Add a GrRenderTask-based dependency
95void GrRenderTask::addDependency(GrRenderTask* dependedOn) {
96 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
Chris Daltondc9a74f2019-09-18 10:26:16 -060097 SkASSERT(!this->dependsOn(dependedOn)); // caller should weed out duplicates
Chris Dalton6b498102019-08-01 14:14:52 -060098
99 fDependencies.push_back(dependedOn);
100 dependedOn->addDependent(this);
101
102 SkDEBUGCODE(this->validate());
103}
104
Greg Danielc30f1a92019-09-06 15:28:58 -0400105void GrRenderTask::addDependenciesFromOtherTask(GrRenderTask* otherTask) {
106 SkASSERT(otherTask);
Chris Daltondc9a74f2019-09-18 10:26:16 -0600107 for (GrRenderTask* task : otherTask->fDependencies) {
Greg Danielc30f1a92019-09-06 15:28:58 -0400108 // The task should not be adding a dependency to itself.
Chris Daltondc9a74f2019-09-18 10:26:16 -0600109 SkASSERT(task != this);
110 if (!this->dependsOn(task)) {
111 this->addDependency(task);
112 }
Greg Danielc30f1a92019-09-06 15:28:58 -0400113 }
114}
115
Chris Dalton6b498102019-08-01 14:14:52 -0600116// Convert from a GrSurface-based dependency to a GrRenderTask one
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400117void GrRenderTask::addDependency(GrDrawingManager* drawingMgr, GrSurfaceProxy* dependedOn,
118 GrMipMapped mipMapped,
Chris Dalton3d770272019-08-14 09:24:37 -0600119 GrTextureResolveManager textureResolveManager,
Chris Dalton08755122019-08-05 16:13:47 -0600120 const GrCaps& caps) {
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600121 // If it is still receiving dependencies, this GrRenderTask shouldn't be closed
122 SkASSERT(!this->isClosed());
Chris Dalton3d770272019-08-14 09:24:37 -0600123
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400124 GrRenderTask* dependedOnTask = drawingMgr->getLastRenderTask(dependedOn);
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600125
126 if (dependedOnTask == this) {
Chris Dalton4ece96d2019-08-30 11:26:39 -0600127 // self-read - presumably for dst reads. We don't need to do anything in this case. The
128 // XferProcessor will detect what is happening and insert a texture barrier.
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600129 SkASSERT(GrMipMapped::kNo == mipMapped);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600130 // We should never attempt a self-read on a surface that has a separate MSAA renderbuffer.
131 SkASSERT(!dependedOn->requiresManualMSAAResolve());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600132 SkASSERT(!dependedOn->asTextureProxy() ||
133 !dependedOn->asTextureProxy()->texPriv().isDeferred());
134 return;
135 }
136
137 if (dependedOnTask) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600138 if (this->dependsOn(dependedOnTask) || fTextureResolveTask == dependedOnTask) {
139 return; // don't add duplicate dependencies
140 }
141
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600142 // We are closing 'dependedOnTask' here bc the current contents of it are what 'this'
143 // renderTask depends on. We need a break in 'dependedOnTask' so that the usage of
144 // that state has a chance to execute.
145 dependedOnTask->makeClosed(caps);
146 }
147
Chris Dalton4ece96d2019-08-30 11:26:39 -0600148 auto resolveFlags = GrSurfaceProxy::ResolveFlags::kNone;
149
150 if (dependedOn->requiresManualMSAAResolve()) {
151 auto* renderTargetProxy = dependedOn->asRenderTargetProxy();
152 SkASSERT(renderTargetProxy);
153 if (renderTargetProxy->isMSAADirty()) {
154 resolveFlags |= GrSurfaceProxy::ResolveFlags::kMSAA;
155 }
156 }
157
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600158 GrTextureProxy* textureProxy = dependedOn->asTextureProxy();
Chris Dalton3d770272019-08-14 09:24:37 -0600159 if (GrMipMapped::kYes == mipMapped) {
160 SkASSERT(textureProxy);
161 if (GrMipMapped::kYes != textureProxy->mipMapped()) {
162 // There are some cases where we might be given a non-mipmapped texture with a mipmap
163 // filter. See skbug.com/7094.
164 mipMapped = GrMipMapped::kNo;
Chris Dalton4ece96d2019-08-30 11:26:39 -0600165 } else if (textureProxy->mipMapsAreDirty()) {
166 resolveFlags |= GrSurfaceProxy::ResolveFlags::kMipMaps;
Chris Dalton3d770272019-08-14 09:24:37 -0600167 }
168 }
169
Chris Dalton4ece96d2019-08-30 11:26:39 -0600170 // Does this proxy have msaa to resolve and/or mipmaps to regenerate?
171 if (GrSurfaceProxy::ResolveFlags::kNone != resolveFlags) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600172 if (!fTextureResolveTask) {
173 fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps);
174 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400175 fTextureResolveTask->addProxy(drawingMgr, sk_ref_sp(dependedOn), resolveFlags, caps);
Chris Daltone2a903e2019-09-18 13:41:50 -0600176
177 // addProxy() should have closed the texture proxy's previous task.
178 SkASSERT(!dependedOnTask || dependedOnTask->isClosed());
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400179 SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
Chris Dalton3d770272019-08-14 09:24:37 -0600180
Chris Dalton4ece96d2019-08-30 11:26:39 -0600181#ifdef SK_DEBUG
Chris Daltone2a903e2019-09-18 13:41:50 -0600182 // addProxy() should have called addDependency (in this instance, recursively) on
183 // fTextureResolveTask.
Chris Dalton4ece96d2019-08-30 11:26:39 -0600184 if (dependedOnTask) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600185 SkASSERT(fTextureResolveTask->dependsOn(dependedOnTask));
Chris Dalton4ece96d2019-08-30 11:26:39 -0600186 }
187 if (textureProxy && textureProxy->texPriv().isDeferred()) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600188 SkASSERT(fTextureResolveTask->fDeferredProxies.back() == textureProxy);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600189 }
Chris Dalton3d770272019-08-14 09:24:37 -0600190
Chris Dalton4ece96d2019-08-30 11:26:39 -0600191 // The GrTextureResolveRenderTask factory should have also marked the proxy clean, set the
Greg Danielf41b2bd2019-08-22 16:19:24 -0400192 // last renderTask on the textureProxy to textureResolveTask, and closed textureResolveTask.
Chris Dalton4ece96d2019-08-30 11:26:39 -0600193 if (GrRenderTargetProxy* renderTargetProxy = dependedOn->asRenderTargetProxy()) {
194 SkASSERT(!renderTargetProxy->isMSAADirty());
195 }
196 if (textureProxy) {
197 SkASSERT(!textureProxy->mipMapsAreDirty());
198 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400199 SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600200#endif
Chris Daltone2a903e2019-09-18 13:41:50 -0600201 return;
202 }
Chris Dalton3d770272019-08-14 09:24:37 -0600203
Chris Daltone2a903e2019-09-18 13:41:50 -0600204 if (textureProxy && textureProxy->texPriv().isDeferred()) {
Chris Dalton3d770272019-08-14 09:24:37 -0600205 fDeferredProxies.push_back(textureProxy);
206 }
207
208 if (dependedOnTask) {
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600209 this->addDependency(dependedOnTask);
Chris Dalton6b498102019-08-01 14:14:52 -0600210 }
Chris Dalton6b498102019-08-01 14:14:52 -0600211}
212
213bool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const {
214 for (int i = 0; i < fDependencies.count(); ++i) {
215 if (fDependencies[i] == dependedOn) {
216 return true;
217 }
218 }
219
220 return false;
221}
222
223
224void GrRenderTask::addDependent(GrRenderTask* dependent) {
225 fDependents.push_back(dependent);
226}
227
228#ifdef SK_DEBUG
229bool GrRenderTask::isDependedent(const GrRenderTask* dependent) const {
230 for (int i = 0; i < fDependents.count(); ++i) {
231 if (fDependents[i] == dependent) {
232 return true;
233 }
234 }
235
236 return false;
237}
238
239void GrRenderTask::validate() const {
240 // TODO: check for loops and duplicates
241
242 for (int i = 0; i < fDependencies.count(); ++i) {
243 SkASSERT(fDependencies[i]->isDependedent(this));
244 }
245}
246#endif
247
248void GrRenderTask::closeThoseWhoDependOnMe(const GrCaps& caps) {
249 for (int i = 0; i < fDependents.count(); ++i) {
250 if (!fDependents[i]->isClosed()) {
251 fDependents[i]->makeClosed(caps);
252 }
253 }
254}
255
256bool GrRenderTask::isInstantiated() const {
Adlai Holler33d569e2020-06-16 14:30:08 -0400257 // Some renderTasks (e.g. GrTransferFromRenderTask) don't have any targets.
258 if (0 == this->numTargets()) {
Greg Danielbbfec9d2019-08-20 10:56:51 -0400259 return true;
260 }
Adlai Holler33d569e2020-06-16 14:30:08 -0400261 GrSurfaceProxy* proxy = this->target(0).proxy();
Greg Danielbbfec9d2019-08-20 10:56:51 -0400262
Greg Daniel16f5c652019-10-29 11:26:01 -0400263 if (!proxy->isInstantiated()) {
Chris Dalton6b498102019-08-01 14:14:52 -0600264 return false;
265 }
266
Greg Daniel16f5c652019-10-29 11:26:01 -0400267 GrSurface* surface = proxy->peekSurface();
Chris Dalton6b498102019-08-01 14:14:52 -0600268 if (surface->wasDestroyed()) {
269 return false;
270 }
271
272 return true;
273}
274
Adlai Holler33d569e2020-06-16 14:30:08 -0400275void GrRenderTask::addTarget(GrDrawingManager* drawingMgr, GrSurfaceProxyView view) {
276 SkASSERT(view);
277 drawingMgr->setLastRenderTask(view.proxy(), this);
278 fTargets.push_back(std::move(view));
279}
280
Chris Dalton6b498102019-08-01 14:14:52 -0600281#ifdef SK_DEBUG
282void GrRenderTask::dump(bool printDependencies) const {
283 SkDebugf("--------------------------------------------------------------\n");
Adlai Holler33d569e2020-06-16 14:30:08 -0400284 SkDebugf("%s - renderTaskID: %d\n", this->name(), fUniqueID);
285
286 if (!fTargets.empty()) {
287 SkDebugf("Targets: \n");
288 for (int i = 0; i < fTargets.count(); ++i) {
289 GrSurfaceProxy* proxy = fTargets[i].proxy();
290 SkDebugf("[%d]: proxyID: %d - surfaceID: %d\n",
291 i,
292 proxy ? proxy->uniqueID().asUInt() : -1,
293 proxy && proxy->peekSurface()
294 ? proxy->peekSurface()->uniqueID().asUInt()
295 : -1);
296 }
297 }
Chris Dalton6b498102019-08-01 14:14:52 -0600298
299 if (printDependencies) {
300 SkDebugf("I rely On (%d): ", fDependencies.count());
301 for (int i = 0; i < fDependencies.count(); ++i) {
302 SkDebugf("%d, ", fDependencies[i]->fUniqueID);
303 }
304 SkDebugf("\n");
305
306 SkDebugf("(%d) Rely On Me: ", fDependents.count());
307 for (int i = 0; i < fDependents.count(); ++i) {
308 SkDebugf("%d, ", fDependents[i]->fUniqueID);
309 }
310 SkDebugf("\n");
311 }
312}
313#endif