Flutter Engine
The Flutter Engine
GrRenderTask.cpp
Go to the documentation of this file.
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
9
15
16uint32_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
26 : fUniqueID(CreateUniqueID())
27 , fFlags(0) {
28}
29
31 SkASSERT(!fDrawingMgr || drawingMgr == fDrawingMgr);
32 SkASSERT(this->isClosed());
33 if (this->isSetFlag(kDisowned_Flag)) {
34 return;
35 }
36 SkDEBUGCODE(fDrawingMgr = nullptr);
38
40 if (this == drawingMgr->getLastRenderTask(target.get())) {
41 drawingMgr->setLastRenderTask(target.get(), nullptr);
42 }
43 }
44}
45
47 SkASSERT(this->isClosed());
48 if (!this->isSkippable()) {
50 this->onMakeSkippable();
51 }
52}
53
54#ifdef SK_DEBUG
55GrRenderTask::~GrRenderTask() {
57}
58
59bool GrRenderTask::deferredProxiesAreInstantiated() const {
60 for (int i = 0; i < fDeferredProxies.size(); ++i) {
62 return false;
63 }
64 }
65
66 return true;
67}
68#endif
69
70void 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
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
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
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
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()) {
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()) {
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) {
224 } else {
225 fDeferredProxies.push_back(textureProxy);
226 }
227 }
228
229 if (dependedOnTask) {
230 this->addDependency(dependedOnTask);
231 }
232}
233
234void 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
244void 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
254bool 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
265void GrRenderTask::addDependent(GrRenderTask* dependent) {
266 fDependents.push_back(dependent);
267}
268
269#ifdef SK_DEBUG
270bool 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
280void 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
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
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)
316void 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) {
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
uint16_t fFlags
Definition: ShapeLayer.cpp:106
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
static constexpr uint32_t SK_InvalidUniqueID
Definition: SkTypes.h:196
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
Definition: SkYUVMath.cpp:629
int find(T *array, int N, T item)
Definition: GrCaps.h:57
GrRecordingContext * getContext()
GrRenderTask * getLastRenderTask(const GrSurfaceProxy *) const
void setLastRenderTask(const GrSurfaceProxy *, GrRenderTask *)
void markMSAADirty(SkIRect dirtyRect)
GrSurfaceProxy * target(int i) const
Definition: GrRenderTask.h:104
virtual void onPrepare(GrOpFlushState *)
Definition: GrRenderTask.h:269
void addDependenciesFromOtherTask(GrRenderTask *otherTask)
void prepare(GrOpFlushState *flushState)
bool isClosed() const
Definition: GrRenderTask.h:56
bool isSetFlag(uint32_t flag) const
Definition: GrRenderTask.h:208
virtual ExpectedOutcome onMakeClosed(GrRecordingContext *, SkIRect *targetUpdateBounds)=0
void setFlag(uint32_t flag)
Definition: GrRenderTask.h:200
bool isInstantiated() const
bool isSkippable() const
Definition: GrRenderTask.h:70
bool dependsOn(const GrRenderTask *dependedOn) const
void makeSkippable()
void addDependency(GrDrawingManager *, GrSurfaceProxy *dependedOn, skgpu::Mipmapped, GrTextureResolveManager, const GrCaps &caps)
virtual void onMakeSkippable()
Definition: GrRenderTask.h:267
skia_private::STArray< 1, sk_sp< GrSurfaceProxy > > fTargets
Definition: GrRenderTask.h:182
void replaceDependency(const GrRenderTask *toReplace, GrRenderTask *replaceWith)
void addTarget(GrDrawingManager *dm, const GrSurfaceProxyView &view)
Definition: GrRenderTask.h:166
void replaceDependent(const GrRenderTask *toReplace, GrRenderTask *replaceWith)
SkDEBUGCODE(~GrRenderTask() override;) void makeClosed(GrRecordingContext *)
virtual void disown(GrDrawingManager *)
skia_private::TArray< GrTextureProxy *, true > fDeferredProxies
Definition: GrRenderTask.h:187
@ kAtlas_Flag
This task is atlas.
Definition: GrRenderTask.h:193
@ kSkippable_Flag
This task is skippable.
Definition: GrRenderTask.h:192
@ kClosed_Flag
This task can't accept any more dependencies.
Definition: GrRenderTask.h:190
@ kDisowned_Flag
This task is disowned by its GrDrawingManager.
Definition: GrRenderTask.h:191
virtual GrRenderTargetProxy * asRenderTargetProxy()
bool requiresManualMSAAResolve() const
virtual GrTextureProxy * asTextureProxy()
GrSurface * peekSurface() const
bool isInstantiated() const
void isUsedAsTaskTarget()
GrTextureProxyPriv texPriv()
void markMipmapsDirty()
skgpu::Mipmapped mipmapped() const
bool mipmapsAreDirty() const
GrTextureResolveRenderTask * newTextureResolveRenderTask(const GrCaps &caps) const
void addProxy(GrDrawingManager *, sk_sp< GrSurfaceProxy > proxy, GrSurfaceProxy::ResolveFlags, const GrCaps &)
const char * c_str() const
Definition: SkString.h:133
T * get() const
Definition: SkRefCnt.h:303
bool empty() const
Definition: SkTArray.h:199
int size() const
Definition: SkTArray.h:421
T & emplace_back(Args &&... args)
Definition: SkTArray.h:248
VkSurfaceKHR surface
Definition: main.cc:49
Mipmapped
Definition: GpuTypes.h:53
Definition: SkRect.h:32
const uintptr_t id