Flutter Engine
The Flutter Engine
Macros | Functions
GrRenderTaskCluster.cpp File Reference
#include "src/gpu/ganesh/GrRenderTaskCluster.h"
#include "src/core/SkTHash.h"
#include "src/gpu/ganesh/GrRenderTask.h"

Go to the source code of this file.

Macros

#define CLUSTER_DEBUGF(...)
 

Functions

static GrSurfaceProxyfirst_target (GrRenderTask *task)
 
static bool depends_on (GrRenderTask *depender, GrRenderTask *dependee)
 
static bool task_cluster_visit (GrRenderTask *task, SkTInternalLList< GrRenderTask > *llist, THashMap< GrSurfaceProxy *, GrRenderTask * > *lastTaskMap)
 
bool GrClusterRenderTasks (SkSpan< const sk_sp< GrRenderTask > > input, SkTInternalLList< GrRenderTask > *llist)
 

Macro Definition Documentation

◆ CLUSTER_DEBUGF

#define CLUSTER_DEBUGF (   ...)

Definition at line 16 of file GrRenderTaskCluster.cpp.

Function Documentation

◆ depends_on()

static bool depends_on ( GrRenderTask depender,
GrRenderTask dependee 
)
static

Definition at line 68 of file GrRenderTaskCluster.cpp.

68 {
69 // Check if depender writes to something dependee reads.
70 // TODO: Establish real DAG dependencies for this during recording? E.g. when a task adds a
71 // target, search backward for the last task that uses the target and add a dep.
72 for (int i = 0; i < depender->numTargets(); i++) {
73 if (dependee->isUsed(depender->target(i))) {
74 CLUSTER_DEBUGF("Cluster: Bail, %s can't write before %s reads from %s.\n",
75 describe_task(depender).c_str(),
76 describe_task(dependee).c_str(),
77 depender->target(i)->getDebugName().c_str());
78 return true;
79 }
80 }
81 // Check for a formal dependency.
82 if (depender->dependsOn(dependee)) {
83 CLUSTER_DEBUGF("Cluster: Bail, %s depends on %s.\n",
84 describe_task(depender).c_str(),
85 describe_task(dependee).c_str());
86 return true;
87 }
88 return false;
89}
#define CLUSTER_DEBUGF(...)
GrSurfaceProxy * target(int i) const
Definition: GrRenderTask.h:104
int numTargets() const
Definition: GrRenderTask.h:103
bool isUsed(GrSurfaceProxy *proxy) const
Definition: GrRenderTask.h:135
bool dependsOn(const GrRenderTask *dependedOn) const

◆ first_target()

static GrSurfaceProxy * first_target ( GrRenderTask task)
static

Definition at line 18 of file GrRenderTaskCluster.cpp.

18{ return task->target(0); }

◆ GrClusterRenderTasks()

bool GrClusterRenderTasks ( SkSpan< const sk_sp< GrRenderTask > >  input,
SkTInternalLList< GrRenderTask > *  llist 
)

Definition at line 159 of file GrRenderTaskCluster.cpp.

160 {
161 SkASSERT(llist->isEmpty());
162
163 if (input.size() < 3) {
164 for (const auto& t : input) {
165 llist->addToTail(t.get());
166 }
167 return false;
168 }
169
170 CLUSTER_DEBUGF("Cluster: Original order is %s\n", describe_tasks(input).c_str());
171
173 bool didReorder = false;
174 for (const auto& t : input) {
175 didReorder |= task_cluster_visit(t.get(), llist, &lastTaskMap);
176 llist->addToTail(t.get());
177 CLUSTER_DEBUGF("Cluster: Output order is now: %s\n", describe_tasks(*llist).c_str());
178 }
179
180#ifdef SK_DEBUG
181 if (didReorder) {
182 validate(input, *llist);
183 }
184#endif
185
186 return didReorder;
187}
static bool task_cluster_visit(GrRenderTask *task, SkTInternalLList< GrRenderTask > *llist, THashMap< GrSurfaceProxy *, GrRenderTask * > *lastTaskMap)
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr size_t size() const
Definition: SkSpan_impl.h:95
void addToTail(T *entry)
bool isEmpty() const

◆ task_cluster_visit()

static bool task_cluster_visit ( GrRenderTask task,
SkTInternalLList< GrRenderTask > *  llist,
THashMap< GrSurfaceProxy *, GrRenderTask * > *  lastTaskMap 
)
static

Definition at line 92 of file GrRenderTaskCluster.cpp.

93 {
94 CLUSTER_DEBUGF("Cluster: ***Step***\nLooking at %s\n",
95 describe_task(task).c_str());
96 if (task->numTargets() != 1) {
97 CLUSTER_DEBUGF("Cluster: %d targets. Emitting barriers.\n", task->numTargets());
98 // Tasks with 0 or multiple targets are treated as full barriers
99 // for all their targets.
100 for (int j = 0; j < task->numTargets(); j++) {
101 if (lastTaskMap->find(task->target(0))) {
102 lastTaskMap->remove(task->target(0));
103 }
104 }
105 return false;
106 }
107
109 GrRenderTask* clusterTail = (lastTaskMap->find(target) ? *lastTaskMap->find(target) : nullptr);
110 lastTaskMap->set(target, task);
111
112 if (!clusterTail) {
113 CLUSTER_DEBUGF("Cluster: Bail, no cluster to extend.\n");
114 return false;
115 }
116
117 CLUSTER_DEBUGF("Cluster: clusterTail is %s.\n", describe_task(clusterTail).c_str());
118
119 if (clusterTail == llist->tail()) {
120 CLUSTER_DEBUGF("Cluster: Bail, cluster is already tail.\n");
121 return false;
122 }
123 GrRenderTask* movedHead = clusterTail->fNext;
124
125 // Now, let's refer to the "cluster" as the chain of tasks with the same target, that we're
126 // hoping to extend by reordering. Let "moved tasks" be the ones we want to move to extend the
127 // cluster.
128 GrRenderTask* clusterHead = clusterTail;
129 while (clusterHead->fPrev
130 && 1 == clusterHead->fPrev->numTargets()
131 && target == first_target(clusterHead->fPrev)) {
132 clusterHead = clusterHead->fPrev;
133 }
134
135 // We can't reorder if any moved task depends on anything in the cluster.
136 // Time complexity here is high, but making a hash set is worse in profiling.
137 for (GrRenderTask* moved = movedHead; moved; moved = moved->fNext) {
138 for (GrRenderTask* passed = clusterHead; passed != movedHead; passed = passed->fNext) {
139 if (depends_on(moved, passed)) {
140 return false;
141 }
142 }
143 }
144
145 // Grab the moved tasks and pull them before clusterHead.
146 for (GrRenderTask* moved = movedHead; moved;) {
147 CLUSTER_DEBUGF("Cluster: Reorder %s behind %s.\n",
148 describe_task(moved).c_str(),
149 describe_task(clusterHead).c_str());
150 // Be careful to save fNext before each move.
151 GrRenderTask* nextMoved = moved->fNext;
152 llist->remove(moved);
153 llist->addBefore(moved, clusterHead);
154 moved = nextMoved;
155 }
156 return true;
157}
static bool depends_on(GrRenderTask *depender, GrRenderTask *dependee)
static GrSurfaceProxy * first_target(GrRenderTask *task)
void addBefore(T *newEntry, T *existingEntry)
void remove(T *entry)
V * find(const K &key) const
Definition: SkTHash.h:494
V * set(K key, V val)
Definition: SkTHash.h:487
void remove(const K &key)
Definition: SkTHash.h:509
uint32_t * target