1 /*
2 * Copyright 2021 Google Inc.
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/GrRenderTaskCluster.h"
9 #include "src/gpu/mock/GrMockRenderTask.h"
10 #include "src/gpu/mock/GrMockSurfaceProxy.h"
11 #include "tests/Test.h"
12
13 typedef void (*CreateGraphPF)(SkTArray<sk_sp<GrMockRenderTask>>* graph,
14 SkTArray<sk_sp<GrMockRenderTask>>* expected);
15
make_proxies(int count,SkTArray<sk_sp<GrSurfaceProxy>> * proxies)16 static void make_proxies(int count, SkTArray<sk_sp<GrSurfaceProxy>>* proxies) {
17 proxies->reset(count);
18 for (int i = 0; i < count; i++) {
19 auto name = SkStringPrintf("%c", 'A' + i);
20 proxies->at(i) = sk_make_sp<GrMockSurfaceProxy>(std::move(name));
21 }
22 }
23
make_tasks(int count,SkTArray<sk_sp<GrMockRenderTask>> * tasks)24 static void make_tasks(int count, SkTArray<sk_sp<GrMockRenderTask>>* tasks) {
25 tasks->reset(count);
26 for (int i = 0; i < count; i++) {
27 tasks->at(i) = sk_make_sp<GrMockRenderTask>();
28 }
29 }
30
31 /*
32 * In: A1 B1 A2
33 * Out: B1 A1 A2
34 */
create_graph0(SkTArray<sk_sp<GrMockRenderTask>> * graph,SkTArray<sk_sp<GrMockRenderTask>> * expected)35 static void create_graph0(SkTArray<sk_sp<GrMockRenderTask>>* graph,
36 SkTArray<sk_sp<GrMockRenderTask>>* expected) {
37 SkTArray<sk_sp<GrSurfaceProxy>> proxies;
38 make_proxies(2, &proxies);
39 make_tasks(3, graph);
40
41 graph->at(0)->addTarget(proxies[0]);
42 graph->at(1)->addTarget(proxies[1]);
43 graph->at(2)->addTarget(proxies[0]);
44 graph->at(2)->addDependency(graph->at(1).get());
45
46 expected->push_back(graph->at(1));
47 expected->push_back(graph->at(0));
48 expected->push_back(graph->at(2));
49 }
50
51 /*
52 * In: A1 B1 A2 C1 A3
53 * Out: B1 C1 A1 A2 A3
54 */
create_graph1(SkTArray<sk_sp<GrMockRenderTask>> * graph,SkTArray<sk_sp<GrMockRenderTask>> * expected)55 static void create_graph1(SkTArray<sk_sp<GrMockRenderTask>>* graph,
56 SkTArray<sk_sp<GrMockRenderTask>>* expected) {
57 SkTArray<sk_sp<GrSurfaceProxy>> proxies;
58 make_proxies(3, &proxies);
59 make_tasks(5, graph);
60
61 graph->at(0)->addTarget(proxies[0]);
62 graph->at(1)->addTarget(proxies[1]);
63 graph->at(2)->addTarget(proxies[0]);
64 graph->at(3)->addTarget(proxies[2]);
65 graph->at(4)->addTarget(proxies[0]);
66
67 expected->push_back(graph->at(1));
68 expected->push_back(graph->at(3));
69 expected->push_back(graph->at(0));
70 expected->push_back(graph->at(2));
71 expected->push_back(graph->at(4));
72 }
73
74 /*
75 * In: A1 B1 A2.
76 * Srcs: A1->B1, B1->A2.
77 * Out: A1 B1 A2. Can't reorder.
78 */
create_graph2(SkTArray<sk_sp<GrMockRenderTask>> * graph,SkTArray<sk_sp<GrMockRenderTask>> * expected)79 static void create_graph2(SkTArray<sk_sp<GrMockRenderTask>>* graph,
80 SkTArray<sk_sp<GrMockRenderTask>>* expected) {
81 SkTArray<sk_sp<GrSurfaceProxy>> proxies;
82 make_proxies(2, &proxies);
83 make_tasks(3, graph);
84
85 graph->at(0)->addTarget(proxies[0]);
86 graph->at(1)->addTarget(proxies[1]);
87 graph->at(2)->addTarget(proxies[0]);
88
89 graph->at(1)->addDependency(graph->at(0).get());
90 graph->at(2)->addDependency(graph->at(1).get());
91
92 // expected is empty. Can't reorder.
93 }
94
95 /*
96 * Write-after-read case.
97 * In: A1 B1 A2 B2
98 * Srcs: A1->B1, A2->B2
99 * Used: B1(A), B2(A)
100 * Out: Can't reorder.
101 */
create_graph3(SkTArray<sk_sp<GrMockRenderTask>> * graph,SkTArray<sk_sp<GrMockRenderTask>> * expected)102 static void create_graph3(SkTArray<sk_sp<GrMockRenderTask>>* graph,
103 SkTArray<sk_sp<GrMockRenderTask>>* expected) {
104 SkTArray<sk_sp<GrSurfaceProxy>> proxies;
105 make_proxies(2, &proxies);
106 make_tasks(4, graph);
107
108 graph->at(0)->addTarget(proxies[0]);
109 graph->at(1)->addTarget(proxies[1]);
110 graph->at(2)->addTarget(proxies[0]);
111 graph->at(3)->addTarget(proxies[1]);
112
113 graph->at(1)->addDependency(graph->at(0).get());
114 graph->at(3)->addDependency(graph->at(2).get());
115
116 graph->at(1)->addUsed(proxies[0]);
117 graph->at(3)->addUsed(proxies[0]);
118
119 // expected is empty. Can't reorder.
120 }
121
DEF_TEST(GrRenderTaskCluster,reporter)122 DEF_TEST(GrRenderTaskCluster, reporter) {
123 CreateGraphPF tests[] = {
124 create_graph0,
125 create_graph1,
126 create_graph2,
127 create_graph3
128 };
129
130 for (size_t i = 0; i < SK_ARRAY_COUNT(tests); ++i) {
131 SkTArray<sk_sp<GrMockRenderTask>> graph;
132 SkTArray<sk_sp<GrMockRenderTask>> expectedOutput;
133
134 (tests[i])(&graph, &expectedOutput);
135
136 SkTInternalLList<GrRenderTask> llist;
137 // TODO: Why does Span not want to convert from sk_sp<GrMockRenderTask> to
138 // `const sk_sp<GrRenderTask>`?
139 SkSpan<const sk_sp<GrRenderTask>> graphSpan(
140 reinterpret_cast<sk_sp<GrRenderTask>*>(graph.data()), graph.count());
141 bool actualResult = GrClusterRenderTasks(graphSpan, &llist);
142
143 if (expectedOutput.empty()) {
144 REPORTER_ASSERT(reporter, !actualResult);
145 } else {
146 REPORTER_ASSERT(reporter, actualResult);
147 // SkTInternalLList::countEntries is debug-only and these tests run in release.
148 int newCount = 0;
149 for ([[maybe_unused]] GrRenderTask* t : llist) {
150 newCount++;
151 }
152 REPORTER_ASSERT(reporter, newCount == expectedOutput.count());
153
154 int j = 0;
155 for (GrRenderTask* n : llist) {
156 REPORTER_ASSERT(reporter, n == expectedOutput[j++].get());
157 }
158 }
159
160 //SkDEBUGCODE(print(graph);)
161 }
162 }
163