Flutter Engine
The Flutter Engine
GrRenderTask.h
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
8#ifndef GrRenderTask_DEFINED
9#define GrRenderTask_DEFINED
10
17
19class GrOpFlushState;
22namespace skgpu {
23namespace ganesh {
24class OpsTask;
25}
26} // namespace skgpu
27
28// This class abstracts a task that targets a single GrSurfaceProxy, participates in the
29// GrDrawingManager's DAG, and implements the onExecute method to modify its target proxy's
30// contents. (e.g., an opsTask that executes a command buffer, a task to regenerate mipmaps, etc.)
31class GrRenderTask : public SkRefCnt {
32public:
35
36 void makeClosed(GrRecordingContext*);
37
38 void prePrepare(GrRecordingContext* context) { this->onPrePrepare(context); }
39
40 // These two methods are only invoked at flush time
41 void prepare(GrOpFlushState* flushState);
42 bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }
43
44 virtual bool requiresExplicitCleanup() const { return false; }
45
46 // Called when this class will survive a flush and needs to truncate its ops and start over.
47 // TODO: ultimately it should be invalid for an op list to survive a flush.
48 // https://bugs.chromium.org/p/skia/issues/detail?id=7111
49 virtual void endFlush(GrDrawingManager*) {}
50
51 // This method "disowns" all the GrSurfaceProxies this RenderTask modifies. In
52 // practice this just means telling the drawingManager to forget the relevant
53 // mappings from surface proxy to last modifying rendertask.
54 virtual void disown(GrDrawingManager*);
55
56 bool isClosed() const { return this->isSetFlag(kClosed_Flag); }
57
58 /**
59 * Make this task skippable. This must be used purely for optimization purposes
60 * at this point as not all tasks will actually skip their work. It would be better if we could
61 * detect tasks that can be skipped automatically. We'd need to support minimal flushes (i.e.,
62 * only flush that which is required for SkSurfaces/SkImages) and the ability to detect
63 * "orphaned tasks" and clean them out from the DAG so they don't indefinitely accumulate.
64 * Finally, we'd probably have to track whether a proxy's backing store was imported or ever
65 * exported to the client in case the client is doing direct reads outside of Skia and thus
66 * may require tasks targeting the proxy to execute even if our DAG contains no reads.
67 */
68 void makeSkippable();
69
70 bool isSkippable() const { return this->isSetFlag(kSkippable_Flag); }
71
72 /** If true no other task should be reordered relative to this task. */
73 bool blocksReordering() const { return this->isSetFlag(kBlocksReordering_Flag); }
74
75 /*
76 * Notify this GrRenderTask that it relies on the contents of 'dependedOn'
77 */
79 GrSurfaceProxy* dependedOn,
82 const GrCaps& caps);
83
84 /*
85 * Notify this GrRenderTask that it relies on the contents of all GrRenderTasks which otherTask
86 * depends on.
87 */
89
90 SkSpan<GrRenderTask*> dependencies() { return SkSpan(fDependencies); }
91 SkSpan<GrRenderTask*> dependents() { return SkSpan(fDependents); }
92
93 void replaceDependency(const GrRenderTask* toReplace, GrRenderTask* replaceWith);
94 void replaceDependent(const GrRenderTask* toReplace, GrRenderTask* replaceWith);
95
96
97 /*
98 * Does this renderTask depend on 'dependedOn'?
99 */
100 bool dependsOn(const GrRenderTask* dependedOn) const;
101
102 uint32_t uniqueID() const { return fUniqueID; }
103 int numTargets() const { return fTargets.size(); }
104 GrSurfaceProxy* target(int i) const { return fTargets[i].get(); }
105
106 /*
107 * Safely cast this GrRenderTask to a OpsTask (if possible).
108 */
109 virtual skgpu::ganesh::OpsTask* asOpsTask() { return nullptr; }
110
111#if defined(GR_TEST_UTILS)
112 /*
113 * Dump out the GrRenderTask dependency DAG
114 */
115 virtual void dump(const SkString& label,
116 SkString indent,
117 bool printDependencies,
118 bool close) const;
119 virtual const char* name() const = 0;
120#endif
121
122#ifdef SK_DEBUG
123 virtual int numClips() const { return 0; }
124
125 virtual void visitProxies_debugOnly(const GrVisitProxyFunc&) const = 0;
126
127 void visitTargetAndSrcProxies_debugOnly(const GrVisitProxyFunc& func) const {
128 this->visitProxies_debugOnly(func);
129 for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
130 func(target.get(), skgpu::Mipmapped::kNo);
131 }
132 }
133#endif
134
135 bool isUsed(GrSurfaceProxy* proxy) const {
136 for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
137 if (target.get() == proxy) {
138 return true;
139 }
140 }
141
142 return this->onIsUsed(proxy);
143 }
144
145 // Feed proxy usage intervals to the GrResourceAllocator class
147
148 // In addition to just the GrSurface being allocated, has the stencil buffer been allocated (if
149 // it is required)?
150 bool isInstantiated() const;
151
152 // Used by GrRenderTaskCluster.
154
155#if defined(GR_TEST_UTILS)
156 const GrTextureResolveRenderTask* resolveTask() const { return fTextureResolveTask; }
157#endif
158protected:
159 SkDEBUGCODE(bool deferredProxiesAreInstantiated() const;)
160
161 // Add a target surface proxy to the list of targets for this task.
162 // This also informs the drawing manager to update the lastRenderTask association.
164
165 // Helper that adds the proxy owned by a view.
167 this->addTarget(dm, view.refProxy());
168 }
169
170 enum class ExpectedOutcome : bool {
171 kTargetUnchanged,
172 kTargetDirty,
173 };
174
175 // Performs any work to finalize this renderTask prior to execution. If returning
176 // ExpectedOutcome::kTargetDirty, the caller is also responsible to fill out the area it will
177 // modify in targetUpdateBounds.
178 //
179 // targetUpdateBounds must not extend beyond the proxy bounds.
180 virtual ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) = 0;
181
183
184 // List of texture proxies whose contents are being prepared on a worker thread
185 // TODO: this list exists so we can fire off the proper upload when an renderTask begins
186 // executing. Can this be replaced?
188
189 enum Flags {
190 kClosed_Flag = 0x01, //!< This task can't accept any more dependencies.
191 kDisowned_Flag = 0x02, //!< This task is disowned by its GrDrawingManager.
192 kSkippable_Flag = 0x04, //!< This task is skippable.
193 kAtlas_Flag = 0x08, //!< This task is atlas.
194 kBlocksReordering_Flag = 0x10, //!< No task can be reordered with respect to this task.
195
196 kWasOutput_Flag = 0x20, //!< Flag for topological sorting
197 kTempMark_Flag = 0x40, //!< Flag for topological sorting
198 };
199
200 void setFlag(uint32_t flag) {
201 fFlags |= flag;
202 }
203
204 void resetFlag(uint32_t flag) {
205 fFlags &= ~flag;
206 }
207
208 bool isSetFlag(uint32_t flag) const {
209 return SkToBool(fFlags & flag);
210 }
211
212 void setIndex(uint32_t index) {
214 SkASSERT(index < (1 << 25));
215 fFlags |= index << 7;
216 }
217
218 uint32_t getIndex() const {
220 return fFlags >> 7;
221 }
222
223private:
224 // for TopoSortTraits, fTextureResolveTask, addDependency
225 friend class GrDrawingManager;
226 friend class GrMockRenderTask;
227
228 // Derived classes can override to indicate usage of proxies _other than target proxies_.
229 // GrRenderTask itself will handle checking the target proxies.
230 virtual bool onIsUsed(GrSurfaceProxy*) const = 0;
231
232 void addDependency(GrRenderTask* dependedOn);
233 void addDependent(GrRenderTask* dependent);
234 SkDEBUGCODE(bool isDependent(const GrRenderTask* dependent) const;)
235 SkDEBUGCODE(void validate() const;)
236
237 static uint32_t CreateUniqueID();
238
239 struct TopoSortTraits {
240 static uint32_t GetIndex(GrRenderTask* renderTask) {
241 return renderTask->getIndex();
242 }
243 static void Output(GrRenderTask* renderTask, uint32_t index) {
244 renderTask->setIndex(index);
245 renderTask->setFlag(kWasOutput_Flag);
246 }
247 static bool WasOutput(const GrRenderTask* renderTask) {
248 return renderTask->isSetFlag(kWasOutput_Flag);
249 }
250 static void SetTempMark(GrRenderTask* renderTask) {
251 renderTask->setFlag(kTempMark_Flag);
252 }
253 static void ResetTempMark(GrRenderTask* renderTask) {
254 renderTask->resetFlag(kTempMark_Flag);
255 }
256 static bool IsTempMarked(const GrRenderTask* renderTask) {
257 return renderTask->isSetFlag(kTempMark_Flag);
258 }
259 static int NumDependencies(const GrRenderTask* renderTask) {
260 return renderTask->fDependencies.size();
261 }
262 static GrRenderTask* Dependency(GrRenderTask* renderTask, int index) {
263 return renderTask->fDependencies[index];
264 }
265 };
266
267 virtual void onMakeSkippable() {}
268 virtual void onPrePrepare(GrRecordingContext*) {} // Only OpsTask currently overrides this
269 virtual void onPrepare(GrOpFlushState*) {} // OpsTask and GrDDLTask override this
270 virtual bool onExecute(GrOpFlushState* flushState) = 0;
271
272 const uint32_t fUniqueID;
273 uint32_t fFlags;
274
275 // 'this' GrRenderTask relies on the output of the GrRenderTasks in 'fDependencies'
277 // 'this' GrRenderTask's output is relied on by the GrRenderTasks in 'fDependents'
279
280 // For performance reasons, we should perform texture resolves back-to-back as much as possible.
281 // (http://skbug.com/9406). To accomplish this, we make and reuse one single resolve task for
282 // each render task, then add it as a dependency during makeClosed().
283 GrTextureResolveRenderTask* fTextureResolveTask = nullptr;
284
285 SkDEBUGCODE(GrDrawingManager *fDrawingMgr = nullptr;)
286};
287
288#endif
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
Definition: GrTypesPriv.h:943
#define SkASSERT(cond)
Definition: SkAssert.h:116
Output
Definition: SkSLBench.cpp:61
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
Definition: SkYUVMath.cpp:629
Definition: GrCaps.h:57
virtual bool onIsUsed(GrSurfaceProxy *) const =0
SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrRenderTask)
GrSurfaceProxy * target(int i) const
Definition: GrRenderTask.h:104
virtual void onPrepare(GrOpFlushState *)
Definition: GrRenderTask.h:269
void addDependenciesFromOtherTask(GrRenderTask *otherTask)
SkSpan< GrRenderTask * > dependencies()
Definition: GrRenderTask.h:90
void setIndex(uint32_t index)
Definition: GrRenderTask.h:212
void prepare(GrOpFlushState *flushState)
bool isClosed() const
Definition: GrRenderTask.h:56
int numTargets() const
Definition: GrRenderTask.h:103
bool isSetFlag(uint32_t flag) const
Definition: GrRenderTask.h:208
virtual void onPrePrepare(GrRecordingContext *)
Definition: GrRenderTask.h:268
virtual ExpectedOutcome onMakeClosed(GrRecordingContext *, SkIRect *targetUpdateBounds)=0
void setFlag(uint32_t flag)
Definition: GrRenderTask.h:200
virtual bool requiresExplicitCleanup() const
Definition: GrRenderTask.h:44
bool isInstantiated() const
void resetFlag(uint32_t flag)
Definition: GrRenderTask.h:204
virtual bool onExecute(GrOpFlushState *flushState)=0
bool isUsed(GrSurfaceProxy *proxy) const
Definition: GrRenderTask.h:135
bool isSkippable() const
Definition: GrRenderTask.h:70
bool dependsOn(const GrRenderTask *dependedOn) const
void makeSkippable()
bool execute(GrOpFlushState *flushState)
Definition: GrRenderTask.h:42
uint32_t getIndex() const
Definition: GrRenderTask.h:218
void prePrepare(GrRecordingContext *context)
Definition: GrRenderTask.h:38
void addDependency(GrDrawingManager *, GrSurfaceProxy *dependedOn, skgpu::Mipmapped, GrTextureResolveManager, const GrCaps &caps)
bool blocksReordering() const
Definition: GrRenderTask.h:73
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)
virtual skgpu::ganesh::OpsTask * asOpsTask()
Definition: GrRenderTask.h:109
SkDEBUGCODE(~GrRenderTask() override;) void makeClosed(GrRecordingContext *)
virtual void disown(GrDrawingManager *)
SkSpan< GrRenderTask * > dependents()
Definition: GrRenderTask.h:91
virtual void endFlush(GrDrawingManager *)
Definition: GrRenderTask.h:49
skia_private::TArray< GrTextureProxy *, true > fDeferredProxies
Definition: GrRenderTask.h:187
uint32_t uniqueID() const
Definition: GrRenderTask.h:102
@ kBlocksReordering_Flag
No task can be reordered with respect to this task.
Definition: GrRenderTask.h:194
@ kWasOutput_Flag
Flag for topological sorting.
Definition: GrRenderTask.h:196
@ 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
@ kTempMark_Flag
Flag for topological sorting.
Definition: GrRenderTask.h:197
virtual void gatherProxyIntervals(GrResourceAllocator *) const =0
sk_sp< GrSurfaceProxy > refProxy() const
int size() const
Definition: SkTArray.h:421
FlutterSemanticsFlag flag
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
Definition: GpuTools.h:21
Mipmapped
Definition: GpuTypes.h:53
Definition: SkRect.h:32