blob: 1cf2efc085874103127ee4f9dc22dec6e37fef6c [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
29GrRenderTask::GrRenderTask(GrSurfaceProxyView targetView)
30 : fTargetView(std::move(targetView))
Chris Dalton6b498102019-08-01 14:14:52 -060031 , fUniqueID(CreateUniqueID())
32 , fFlags(0) {
Chris Dalton6b498102019-08-01 14:14:52 -060033}
34
Adlai Hollerd71b7b02020-06-08 15:55:00 -040035void GrRenderTask::disown(GrDrawingManager* drawingMgr) {
36 if (this->isSetFlag(kDisowned_Flag)) {
37 return;
Chris Dalton6b498102019-08-01 14:14:52 -060038 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -040039 this->setFlag(kDisowned_Flag);
40 GrSurfaceProxy* proxy = fTargetView.proxy();
41 if (proxy && this == drawingMgr->getLastRenderTask(proxy)) {
42 // Ensure the drawing manager doesn't hold a dangling pointer.
43 drawingMgr->setLastRenderTask(proxy, nullptr);
44 }
45}
46
47GrRenderTask::~GrRenderTask() {
48 SkASSERT(this->isSetFlag(kDisowned_Flag));
Chris Dalton6b498102019-08-01 14:14:52 -060049}
50
51#ifdef SK_DEBUG
52bool GrRenderTask::deferredProxiesAreInstantiated() const {
53 for (int i = 0; i < fDeferredProxies.count(); ++i) {
54 if (!fDeferredProxies[i]->isInstantiated()) {
55 return false;
56 }
57 }
58
59 return true;
60}
61#endif
62
Chris Daltonaa3cbb82019-08-21 00:01:21 -060063void GrRenderTask::makeClosed(const GrCaps& caps) {
64 if (this->isClosed()) {
65 return;
66 }
67
Chris Dalton16a33c62019-09-24 22:19:17 -060068 SkIRect targetUpdateBounds;
69 if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) {
Greg Daniel16f5c652019-10-29 11:26:01 -040070 GrSurfaceProxy* proxy = fTargetView.proxy();
Greg Daniel16f5c652019-10-29 11:26:01 -040071 if (proxy->requiresManualMSAAResolve()) {
72 SkASSERT(fTargetView.asRenderTargetProxy());
Greg Daniel242536f2020-02-13 14:12:46 -050073 fTargetView.asRenderTargetProxy()->markMSAADirty(targetUpdateBounds,
74 fTargetView.origin());
Chris Dalton4ece96d2019-08-30 11:26:39 -060075 }
Greg Daniel16f5c652019-10-29 11:26:01 -040076 GrTextureProxy* textureProxy = fTargetView.asTextureProxy();
Chris Daltonaa3cbb82019-08-21 00:01:21 -060077 if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
78 textureProxy->markMipMapsDirty();
79 }
80 }
81
Chris Daltone2a903e2019-09-18 13:41:50 -060082 if (fTextureResolveTask) {
83 this->addDependency(fTextureResolveTask);
84 fTextureResolveTask->makeClosed(caps);
85 fTextureResolveTask = nullptr;
86 }
87
Chris Daltonaa3cbb82019-08-21 00:01:21 -060088 this->setFlag(kClosed_Flag);
89}
90
Chris Dalton6b498102019-08-01 14:14:52 -060091void GrRenderTask::prepare(GrOpFlushState* flushState) {
92 for (int i = 0; i < fDeferredProxies.count(); ++i) {
93 fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
94 }
95
96 this->onPrepare(flushState);
97}
98
99// Add a GrRenderTask-based dependency
100void GrRenderTask::addDependency(GrRenderTask* dependedOn) {
101 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
Chris Daltondc9a74f2019-09-18 10:26:16 -0600102 SkASSERT(!this->dependsOn(dependedOn)); // caller should weed out duplicates
Chris Dalton6b498102019-08-01 14:14:52 -0600103
104 fDependencies.push_back(dependedOn);
105 dependedOn->addDependent(this);
106
107 SkDEBUGCODE(this->validate());
108}
109
Greg Danielc30f1a92019-09-06 15:28:58 -0400110void GrRenderTask::addDependenciesFromOtherTask(GrRenderTask* otherTask) {
111 SkASSERT(otherTask);
Chris Daltondc9a74f2019-09-18 10:26:16 -0600112 for (GrRenderTask* task : otherTask->fDependencies) {
Greg Danielc30f1a92019-09-06 15:28:58 -0400113 // The task should not be adding a dependency to itself.
Chris Daltondc9a74f2019-09-18 10:26:16 -0600114 SkASSERT(task != this);
115 if (!this->dependsOn(task)) {
116 this->addDependency(task);
117 }
Greg Danielc30f1a92019-09-06 15:28:58 -0400118 }
119}
120
Chris Dalton6b498102019-08-01 14:14:52 -0600121// Convert from a GrSurface-based dependency to a GrRenderTask one
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400122void GrRenderTask::addDependency(GrDrawingManager* drawingMgr, GrSurfaceProxy* dependedOn,
123 GrMipMapped mipMapped,
Chris Dalton3d770272019-08-14 09:24:37 -0600124 GrTextureResolveManager textureResolveManager,
Chris Dalton08755122019-08-05 16:13:47 -0600125 const GrCaps& caps) {
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600126 // If it is still receiving dependencies, this GrRenderTask shouldn't be closed
127 SkASSERT(!this->isClosed());
Chris Dalton3d770272019-08-14 09:24:37 -0600128
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400129 GrRenderTask* dependedOnTask = drawingMgr->getLastRenderTask(dependedOn);
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600130
131 if (dependedOnTask == this) {
Chris Dalton4ece96d2019-08-30 11:26:39 -0600132 // self-read - presumably for dst reads. We don't need to do anything in this case. The
133 // XferProcessor will detect what is happening and insert a texture barrier.
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600134 SkASSERT(GrMipMapped::kNo == mipMapped);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600135 // We should never attempt a self-read on a surface that has a separate MSAA renderbuffer.
136 SkASSERT(!dependedOn->requiresManualMSAAResolve());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600137 SkASSERT(!dependedOn->asTextureProxy() ||
138 !dependedOn->asTextureProxy()->texPriv().isDeferred());
139 return;
140 }
141
142 if (dependedOnTask) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600143 if (this->dependsOn(dependedOnTask) || fTextureResolveTask == dependedOnTask) {
144 return; // don't add duplicate dependencies
145 }
146
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600147 // We are closing 'dependedOnTask' here bc the current contents of it are what 'this'
148 // renderTask depends on. We need a break in 'dependedOnTask' so that the usage of
149 // that state has a chance to execute.
150 dependedOnTask->makeClosed(caps);
151 }
152
Chris Dalton4ece96d2019-08-30 11:26:39 -0600153 auto resolveFlags = GrSurfaceProxy::ResolveFlags::kNone;
154
155 if (dependedOn->requiresManualMSAAResolve()) {
156 auto* renderTargetProxy = dependedOn->asRenderTargetProxy();
157 SkASSERT(renderTargetProxy);
158 if (renderTargetProxy->isMSAADirty()) {
159 resolveFlags |= GrSurfaceProxy::ResolveFlags::kMSAA;
160 }
161 }
162
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600163 GrTextureProxy* textureProxy = dependedOn->asTextureProxy();
Chris Dalton3d770272019-08-14 09:24:37 -0600164 if (GrMipMapped::kYes == mipMapped) {
165 SkASSERT(textureProxy);
166 if (GrMipMapped::kYes != textureProxy->mipMapped()) {
167 // There are some cases where we might be given a non-mipmapped texture with a mipmap
168 // filter. See skbug.com/7094.
169 mipMapped = GrMipMapped::kNo;
Chris Dalton4ece96d2019-08-30 11:26:39 -0600170 } else if (textureProxy->mipMapsAreDirty()) {
171 resolveFlags |= GrSurfaceProxy::ResolveFlags::kMipMaps;
Chris Dalton3d770272019-08-14 09:24:37 -0600172 }
173 }
174
Chris Dalton4ece96d2019-08-30 11:26:39 -0600175 // Does this proxy have msaa to resolve and/or mipmaps to regenerate?
176 if (GrSurfaceProxy::ResolveFlags::kNone != resolveFlags) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600177 if (!fTextureResolveTask) {
178 fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps);
179 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400180 fTextureResolveTask->addProxy(drawingMgr, sk_ref_sp(dependedOn), resolveFlags, caps);
Chris Daltone2a903e2019-09-18 13:41:50 -0600181
182 // addProxy() should have closed the texture proxy's previous task.
183 SkASSERT(!dependedOnTask || dependedOnTask->isClosed());
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400184 SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
Chris Dalton3d770272019-08-14 09:24:37 -0600185
Chris Dalton4ece96d2019-08-30 11:26:39 -0600186#ifdef SK_DEBUG
Chris Daltone2a903e2019-09-18 13:41:50 -0600187 // addProxy() should have called addDependency (in this instance, recursively) on
188 // fTextureResolveTask.
Chris Dalton4ece96d2019-08-30 11:26:39 -0600189 if (dependedOnTask) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600190 SkASSERT(fTextureResolveTask->dependsOn(dependedOnTask));
Chris Dalton4ece96d2019-08-30 11:26:39 -0600191 }
192 if (textureProxy && textureProxy->texPriv().isDeferred()) {
Chris Daltone2a903e2019-09-18 13:41:50 -0600193 SkASSERT(fTextureResolveTask->fDeferredProxies.back() == textureProxy);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600194 }
Chris Dalton3d770272019-08-14 09:24:37 -0600195
Chris Dalton4ece96d2019-08-30 11:26:39 -0600196 // The GrTextureResolveRenderTask factory should have also marked the proxy clean, set the
Greg Danielf41b2bd2019-08-22 16:19:24 -0400197 // last renderTask on the textureProxy to textureResolveTask, and closed textureResolveTask.
Chris Dalton4ece96d2019-08-30 11:26:39 -0600198 if (GrRenderTargetProxy* renderTargetProxy = dependedOn->asRenderTargetProxy()) {
199 SkASSERT(!renderTargetProxy->isMSAADirty());
200 }
201 if (textureProxy) {
202 SkASSERT(!textureProxy->mipMapsAreDirty());
203 }
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400204 SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
Chris Dalton4ece96d2019-08-30 11:26:39 -0600205#endif
Chris Daltone2a903e2019-09-18 13:41:50 -0600206 return;
207 }
Chris Dalton3d770272019-08-14 09:24:37 -0600208
Chris Daltone2a903e2019-09-18 13:41:50 -0600209 if (textureProxy && textureProxy->texPriv().isDeferred()) {
Chris Dalton3d770272019-08-14 09:24:37 -0600210 fDeferredProxies.push_back(textureProxy);
211 }
212
213 if (dependedOnTask) {
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600214 this->addDependency(dependedOnTask);
Chris Dalton6b498102019-08-01 14:14:52 -0600215 }
Chris Dalton6b498102019-08-01 14:14:52 -0600216}
217
218bool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const {
219 for (int i = 0; i < fDependencies.count(); ++i) {
220 if (fDependencies[i] == dependedOn) {
221 return true;
222 }
223 }
224
225 return false;
226}
227
228
229void GrRenderTask::addDependent(GrRenderTask* dependent) {
230 fDependents.push_back(dependent);
231}
232
233#ifdef SK_DEBUG
234bool GrRenderTask::isDependedent(const GrRenderTask* dependent) const {
235 for (int i = 0; i < fDependents.count(); ++i) {
236 if (fDependents[i] == dependent) {
237 return true;
238 }
239 }
240
241 return false;
242}
243
244void GrRenderTask::validate() const {
245 // TODO: check for loops and duplicates
246
247 for (int i = 0; i < fDependencies.count(); ++i) {
248 SkASSERT(fDependencies[i]->isDependedent(this));
249 }
250}
251#endif
252
253void GrRenderTask::closeThoseWhoDependOnMe(const GrCaps& caps) {
254 for (int i = 0; i < fDependents.count(); ++i) {
255 if (!fDependents[i]->isClosed()) {
256 fDependents[i]->makeClosed(caps);
257 }
258 }
259}
260
261bool GrRenderTask::isInstantiated() const {
Greg Danielbbfec9d2019-08-20 10:56:51 -0400262 // Some renderTasks (e.g. GrTransferFromRenderTask) don't have a target.
Greg Daniel16f5c652019-10-29 11:26:01 -0400263 GrSurfaceProxy* proxy = fTargetView.proxy();
264 if (!proxy) {
Greg Danielbbfec9d2019-08-20 10:56:51 -0400265 return true;
266 }
267
Greg Daniel16f5c652019-10-29 11:26:01 -0400268 if (!proxy->isInstantiated()) {
Chris Dalton6b498102019-08-01 14:14:52 -0600269 return false;
270 }
271
Greg Daniel16f5c652019-10-29 11:26:01 -0400272 GrSurface* surface = proxy->peekSurface();
Chris Dalton6b498102019-08-01 14:14:52 -0600273 if (surface->wasDestroyed()) {
274 return false;
275 }
276
277 return true;
278}
279
280#ifdef SK_DEBUG
281void GrRenderTask::dump(bool printDependencies) const {
282 SkDebugf("--------------------------------------------------------------\n");
Greg Daniel16f5c652019-10-29 11:26:01 -0400283 GrSurfaceProxy* proxy = fTargetView.proxy();
Robert Phillips44e2c5f2020-04-14 13:00:04 -0400284 SkDebugf("%s - renderTaskID: %d - proxyID: %d - surfaceID: %d\n",
285 this->name(), fUniqueID,
Greg Daniel16f5c652019-10-29 11:26:01 -0400286 proxy ? proxy->uniqueID().asUInt() : -1,
287 proxy && proxy->peekSurface()
288 ? proxy->peekSurface()->uniqueID().asUInt()
Chris Dalton6b498102019-08-01 14:14:52 -0600289 : -1);
290
291 if (printDependencies) {
292 SkDebugf("I rely On (%d): ", fDependencies.count());
293 for (int i = 0; i < fDependencies.count(); ++i) {
294 SkDebugf("%d, ", fDependencies[i]->fUniqueID);
295 }
296 SkDebugf("\n");
297
298 SkDebugf("(%d) Rely On Me: ", fDependents.count());
299 for (int i = 0; i < fDependents.count(); ++i) {
300 SkDebugf("%d, ", fDependents[i]->fUniqueID);
301 }
302 SkDebugf("\n");
303 }
304}
305#endif