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