xref: /aosp_15_r20/external/skia/tests/RasterPipelineCodeGeneratorTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
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/SkColor.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRasterPipeline.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLCompiler.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramKind.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramSettings.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLUtil.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLRasterPipelineBuilder.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/codegen/SkSLRasterPipelineCodeGenerator.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLFunctionDeclaration.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgram.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/tracing/SkSLDebugTracePriv.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
24*c8dee2aaSAndroid Build Coastguard Worker #include <optional>
25*c8dee2aaSAndroid Build Coastguard Worker #include <sstream>
26*c8dee2aaSAndroid Build Coastguard Worker #include <string>
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker //#define DUMP_PROGRAMS 1
29*c8dee2aaSAndroid Build Coastguard Worker #if defined(DUMP_PROGRAMS)
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStreamPriv.h"
31*c8dee2aaSAndroid Build Coastguard Worker #endif
32*c8dee2aaSAndroid Build Coastguard Worker 
test(skiatest::Reporter * r,const char * src,SkSpan<const float> uniforms,SkColor4f startingColor,std::optional<SkColor4f> expectedResult)33*c8dee2aaSAndroid Build Coastguard Worker static void test(skiatest::Reporter* r,
34*c8dee2aaSAndroid Build Coastguard Worker                  const char* src,
35*c8dee2aaSAndroid Build Coastguard Worker                  SkSpan<const float> uniforms,
36*c8dee2aaSAndroid Build Coastguard Worker                  SkColor4f startingColor,
37*c8dee2aaSAndroid Build Coastguard Worker                  std::optional<SkColor4f> expectedResult) {
38*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Compiler compiler;
39*c8dee2aaSAndroid Build Coastguard Worker     SkSL::ProgramSettings settings;
40*c8dee2aaSAndroid Build Coastguard Worker     settings.fMaxVersionAllowed = SkSL::Version::k300;
41*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
42*c8dee2aaSAndroid Build Coastguard Worker             SkSL::ProgramKind::kRuntimeColorFilter, std::string(src), settings);
43*c8dee2aaSAndroid Build Coastguard Worker     if (!program) {
44*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
45*c8dee2aaSAndroid Build Coastguard Worker         return;
46*c8dee2aaSAndroid Build Coastguard Worker     }
47*c8dee2aaSAndroid Build Coastguard Worker     const SkSL::FunctionDeclaration* main = program->getFunction("main");
48*c8dee2aaSAndroid Build Coastguard Worker     if (!main) {
49*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "Program must have a 'main' function");
50*c8dee2aaSAndroid Build Coastguard Worker         return;
51*c8dee2aaSAndroid Build Coastguard Worker     }
52*c8dee2aaSAndroid Build Coastguard Worker     SkArenaAlloc alloc(/*firstHeapAllocation=*/1000);
53*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline pipeline(&alloc);
54*c8dee2aaSAndroid Build Coastguard Worker     pipeline.appendConstantColor(&alloc, startingColor);
55*c8dee2aaSAndroid Build Coastguard Worker     SkSL::DebugTracePriv debugTrace;
56*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkSL::RP::Program> rasterProg =
57*c8dee2aaSAndroid Build Coastguard Worker             SkSL::MakeRasterPipelineProgram(*program, *main->definition(), &debugTrace);
58*c8dee2aaSAndroid Build Coastguard Worker     if (!rasterProg && !expectedResult.has_value()) {
59*c8dee2aaSAndroid Build Coastguard Worker         // We didn't get a program, as expected. Test passes.
60*c8dee2aaSAndroid Build Coastguard Worker         return;
61*c8dee2aaSAndroid Build Coastguard Worker     }
62*c8dee2aaSAndroid Build Coastguard Worker     if (!rasterProg && expectedResult.has_value()) {
63*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "MakeRasterPipelineProgram failed");
64*c8dee2aaSAndroid Build Coastguard Worker         return;
65*c8dee2aaSAndroid Build Coastguard Worker     }
66*c8dee2aaSAndroid Build Coastguard Worker     if (rasterProg && !expectedResult.has_value()) {
67*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "MakeRasterPipelineProgram should have failed, but didn't");
68*c8dee2aaSAndroid Build Coastguard Worker         return;
69*c8dee2aaSAndroid Build Coastguard Worker     }
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker #if defined(DUMP_PROGRAMS)
72*c8dee2aaSAndroid Build Coastguard Worker     // Dump the program instructions via SkDebugf.
73*c8dee2aaSAndroid Build Coastguard Worker     SkDebugf("-----\n\n");
74*c8dee2aaSAndroid Build Coastguard Worker     SkDebugfStream stream;
75*c8dee2aaSAndroid Build Coastguard Worker     rasterProg->dump(&stream);
76*c8dee2aaSAndroid Build Coastguard Worker     SkDebugf("\n-----\n\n");
77*c8dee2aaSAndroid Build Coastguard Worker #endif
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     // Append the SkSL program to the raster pipeline.
80*c8dee2aaSAndroid Build Coastguard Worker     rasterProg->appendStages(&pipeline, &alloc, /*callbacks=*/nullptr, uniforms);
81*c8dee2aaSAndroid Build Coastguard Worker 
82*c8dee2aaSAndroid Build Coastguard Worker     // Move the float values from RGBA into an 8888 memory buffer.
83*c8dee2aaSAndroid Build Coastguard Worker     uint32_t out[SkRasterPipeline_kMaxStride_highp] = {};
84*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline_MemoryCtx outCtx{/*pixels=*/out, /*stride=*/SkRasterPipeline_kMaxStride_highp};
85*c8dee2aaSAndroid Build Coastguard Worker     pipeline.append(SkRasterPipelineOp::store_8888, &outCtx);
86*c8dee2aaSAndroid Build Coastguard Worker     pipeline.run(0, 0, 1, 1);
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker     // Make sure the first pixel (exclusively) of `out` matches RGBA.
89*c8dee2aaSAndroid Build Coastguard Worker     uint32_t expected = expectedResult->toBytes_RGBA();
90*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, out[0] == expected,
91*c8dee2aaSAndroid Build Coastguard Worker                     "Got:%02X%02X%02X%02X Expected:%02X%02X%02X%02X",
92*c8dee2aaSAndroid Build Coastguard Worker                     (out[0] >> 24) & 0xFF,
93*c8dee2aaSAndroid Build Coastguard Worker                     (out[0] >> 16) & 0xFF,
94*c8dee2aaSAndroid Build Coastguard Worker                     (out[0] >> 8) & 0xFF,
95*c8dee2aaSAndroid Build Coastguard Worker                     out[0] & 0xFF,
96*c8dee2aaSAndroid Build Coastguard Worker                     (expected >> 24) & 0xFF,
97*c8dee2aaSAndroid Build Coastguard Worker                     (expected >> 16) & 0xFF,
98*c8dee2aaSAndroid Build Coastguard Worker                     (expected >> 8) & 0xFF,
99*c8dee2aaSAndroid Build Coastguard Worker                     expected & 0xFF);
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker     // Make sure the rest of the pixels are untouched.
102*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 1; i < std::size(out); ++i) {
103*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, out[i] == 0);
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineCodeGeneratorNestedTernaryTest,r)107*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineCodeGeneratorNestedTernaryTest, r) {
108*c8dee2aaSAndroid Build Coastguard Worker     // Add in your SkSL here.
109*c8dee2aaSAndroid Build Coastguard Worker     test(r,
110*c8dee2aaSAndroid Build Coastguard Worker          R"__SkSL__(
111*c8dee2aaSAndroid Build Coastguard Worker              half4 main(half4) {
112*c8dee2aaSAndroid Build Coastguard Worker                  half three = 3, one = 1, two = 2;
113*c8dee2aaSAndroid Build Coastguard Worker                  half result = (three > (one > two ? 2.0 : 5.0)) ? 1.0 : 0.499;
114*c8dee2aaSAndroid Build Coastguard Worker                  return half4(result);
115*c8dee2aaSAndroid Build Coastguard Worker              }
116*c8dee2aaSAndroid Build Coastguard Worker          )__SkSL__",
117*c8dee2aaSAndroid Build Coastguard Worker          /*uniforms=*/{},
118*c8dee2aaSAndroid Build Coastguard Worker          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
119*c8dee2aaSAndroid Build Coastguard Worker          /*expectedResult=*/SkColor4f{0.499f, 0.499f, 0.499f, 0.499f});
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineCodeGeneratorArithmeticTest,r)122*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineCodeGeneratorArithmeticTest, r) {
123*c8dee2aaSAndroid Build Coastguard Worker     test(r,
124*c8dee2aaSAndroid Build Coastguard Worker          R"__SkSL__(
125*c8dee2aaSAndroid Build Coastguard Worker             half4 main(half4) {
126*c8dee2aaSAndroid Build Coastguard Worker                 const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
127*c8dee2aaSAndroid Build Coastguard Worker 
128*c8dee2aaSAndroid Build Coastguard Worker                 half a = 3.0, b = 4.0, c = a + b - 2.0;
129*c8dee2aaSAndroid Build Coastguard Worker                 if (a*a + b*b == c*c*c/5.0) {
130*c8dee2aaSAndroid Build Coastguard Worker                     int A = 3, B = 4, C = A + B - 2;
131*c8dee2aaSAndroid Build Coastguard Worker                     if (A*A + B*B == C*C*C/5) {
132*c8dee2aaSAndroid Build Coastguard Worker                         return colorGreen;
133*c8dee2aaSAndroid Build Coastguard Worker                     }
134*c8dee2aaSAndroid Build Coastguard Worker                 }
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker                 return colorRed;
137*c8dee2aaSAndroid Build Coastguard Worker             }
138*c8dee2aaSAndroid Build Coastguard Worker          )__SkSL__",
139*c8dee2aaSAndroid Build Coastguard Worker          /*uniforms=*/{},
140*c8dee2aaSAndroid Build Coastguard Worker          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
141*c8dee2aaSAndroid Build Coastguard Worker          /*expectedResult=*/SkColor4f{0.0f, 1.0f, 0.0f, 1.0f});
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineCodeGeneratorCoercedTypeTest,r)144*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineCodeGeneratorCoercedTypeTest, r) {
145*c8dee2aaSAndroid Build Coastguard Worker     static constexpr float kUniforms[] = {0.0, 1.0, 0.0, 1.0,
146*c8dee2aaSAndroid Build Coastguard Worker                                           1.0, 0.0, 0.0, 1.0};
147*c8dee2aaSAndroid Build Coastguard Worker     test(r,
148*c8dee2aaSAndroid Build Coastguard Worker          R"__SkSL__(
149*c8dee2aaSAndroid Build Coastguard Worker              uniform half4 colorGreen;
150*c8dee2aaSAndroid Build Coastguard Worker              uniform float4 colorRed;
151*c8dee2aaSAndroid Build Coastguard Worker              half4 main(half4 color) {
152*c8dee2aaSAndroid Build Coastguard Worker                  return ((colorGreen + colorRed) == float4(1.0, 1.0, 0.0, 2.0)) ? colorGreen
153*c8dee2aaSAndroid Build Coastguard Worker                                                                                 : colorGreen.gr01;
154*c8dee2aaSAndroid Build Coastguard Worker              }
155*c8dee2aaSAndroid Build Coastguard Worker          )__SkSL__",
156*c8dee2aaSAndroid Build Coastguard Worker          kUniforms,
157*c8dee2aaSAndroid Build Coastguard Worker          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
158*c8dee2aaSAndroid Build Coastguard Worker          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
159*c8dee2aaSAndroid Build Coastguard Worker }
160*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineCodeGeneratorIdentitySwizzle,r)161*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineCodeGeneratorIdentitySwizzle, r) {
162*c8dee2aaSAndroid Build Coastguard Worker     static constexpr float kUniforms[] = {0.0, 1.0, 0.0, 1.0,
163*c8dee2aaSAndroid Build Coastguard Worker                                           1.0, 0.0, 0.0, 1.0};
164*c8dee2aaSAndroid Build Coastguard Worker     test(r,
165*c8dee2aaSAndroid Build Coastguard Worker          R"__SkSL__(
166*c8dee2aaSAndroid Build Coastguard Worker 
167*c8dee2aaSAndroid Build Coastguard Worker uniform half4 colorGreen, colorRed;
168*c8dee2aaSAndroid Build Coastguard Worker 
169*c8dee2aaSAndroid Build Coastguard Worker const int SEVEN = 7, TEN = 10;
170*c8dee2aaSAndroid Build Coastguard Worker const half4x4 MATRIXFIVE = half4x4(5);
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker noinline bool verify_const_globals(int seven, int ten, half4x4 matrixFive) {
173*c8dee2aaSAndroid Build Coastguard Worker     return seven == 7 && ten == 10 && matrixFive == half4x4(5);
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker half4 main(float4) {
177*c8dee2aaSAndroid Build Coastguard Worker     return verify_const_globals(SEVEN, TEN, MATRIXFIVE) ? colorGreen : colorRed;
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker 
180*c8dee2aaSAndroid Build Coastguard Worker          )__SkSL__",
181*c8dee2aaSAndroid Build Coastguard Worker          kUniforms,
182*c8dee2aaSAndroid Build Coastguard Worker          /*startingColor=*/SkColor4f{0.5, 1.0, 0.0, 0.25},
183*c8dee2aaSAndroid Build Coastguard Worker          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineCodeGeneratorBitwiseNotTest,r)187*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineCodeGeneratorBitwiseNotTest, r) {
188*c8dee2aaSAndroid Build Coastguard Worker     static constexpr int32_t kUniforms[] = { 0,  12,  3456,  4567890,
189*c8dee2aaSAndroid Build Coastguard Worker                                             ~0, ~12, ~3456, ~4567890};
190*c8dee2aaSAndroid Build Coastguard Worker     test(r,
191*c8dee2aaSAndroid Build Coastguard Worker          R"__SkSL__(
192*c8dee2aaSAndroid Build Coastguard Worker             uniform int4 value, expected;
193*c8dee2aaSAndroid Build Coastguard Worker             const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
194*c8dee2aaSAndroid Build Coastguard Worker 
195*c8dee2aaSAndroid Build Coastguard Worker             half4 main(vec4) {
196*c8dee2aaSAndroid Build Coastguard Worker                 return (~value.x    == expected.x     &&
197*c8dee2aaSAndroid Build Coastguard Worker                         ~value.xy   == expected.xy    &&
198*c8dee2aaSAndroid Build Coastguard Worker                         ~value.xyz  == expected.xyz   &&
199*c8dee2aaSAndroid Build Coastguard Worker                         ~value.xyzw == expected.xyzw) ? colorGreen : colorRed;
200*c8dee2aaSAndroid Build Coastguard Worker             }
201*c8dee2aaSAndroid Build Coastguard Worker          )__SkSL__",
202*c8dee2aaSAndroid Build Coastguard Worker          SkSpan((const float*)kUniforms, std::size(kUniforms)),
203*c8dee2aaSAndroid Build Coastguard Worker          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
204*c8dee2aaSAndroid Build Coastguard Worker          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineCodeGeneratorComparisonIntrinsicTest,r)207*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineCodeGeneratorComparisonIntrinsicTest, r) {
208*c8dee2aaSAndroid Build Coastguard Worker     test(r,
209*c8dee2aaSAndroid Build Coastguard Worker          R"__SkSL__(
210*c8dee2aaSAndroid Build Coastguard Worker             half4 main(vec4) {
211*c8dee2aaSAndroid Build Coastguard Worker                 const half4 colorGreen = half4(0,1,0,1), colorRed = half4(1,0,0,1);
212*c8dee2aaSAndroid Build Coastguard Worker                 half4 a = half4(1, 2, 0, 1),
213*c8dee2aaSAndroid Build Coastguard Worker                       b = half4(2, 2, 1, 0);
214*c8dee2aaSAndroid Build Coastguard Worker                 int3  c = int3(1111, 3333, 5555),
215*c8dee2aaSAndroid Build Coastguard Worker                       d = int3(1111, 5555, 3333);
216*c8dee2aaSAndroid Build Coastguard Worker                 uint2 e = uint2(1111111111u, 222),
217*c8dee2aaSAndroid Build Coastguard Worker                       f = uint2(3333333333u, 222);
218*c8dee2aaSAndroid Build Coastguard Worker                 return (lessThan(a, b)         == bool4(true, false, true, false)  &&
219*c8dee2aaSAndroid Build Coastguard Worker                         lessThan(c, d)         == bool3(false, true, false)        &&
220*c8dee2aaSAndroid Build Coastguard Worker                         lessThan(e, f)         == bool2(true, false)               &&
221*c8dee2aaSAndroid Build Coastguard Worker                         greaterThan(a, b)      == bool4(false, false, false, true) &&
222*c8dee2aaSAndroid Build Coastguard Worker                         greaterThan(c, d)      == bool3(false, false, true)        &&
223*c8dee2aaSAndroid Build Coastguard Worker                         greaterThan(e, f)      == bool2(false, false)              &&
224*c8dee2aaSAndroid Build Coastguard Worker                         lessThanEqual(a, b)    == bool4(true, true, true, false)   &&
225*c8dee2aaSAndroid Build Coastguard Worker                         lessThanEqual(c, d)    == bool3(true, true, false)         &&
226*c8dee2aaSAndroid Build Coastguard Worker                         lessThanEqual(e, f)    == bool2(true, true)                &&
227*c8dee2aaSAndroid Build Coastguard Worker                         greaterThanEqual(a, b) == bool4(false, true, false, true)  &&
228*c8dee2aaSAndroid Build Coastguard Worker                         greaterThanEqual(c, d) == bool3(true, false, true)         &&
229*c8dee2aaSAndroid Build Coastguard Worker                         greaterThanEqual(e, f) == bool2(false, true)               &&
230*c8dee2aaSAndroid Build Coastguard Worker                         equal(a, b)            == bool4(false, true, false, false) &&
231*c8dee2aaSAndroid Build Coastguard Worker                         equal(c, d)            == bool3(true, false, false)        &&
232*c8dee2aaSAndroid Build Coastguard Worker                         equal(e, f)            == bool2(false, true)               &&
233*c8dee2aaSAndroid Build Coastguard Worker                         notEqual(a, b)         == bool4(true, false, true, true)   &&
234*c8dee2aaSAndroid Build Coastguard Worker                         notEqual(c, d)         == bool3(false, true, true)         &&
235*c8dee2aaSAndroid Build Coastguard Worker                         notEqual(e, f)         == bool2(true, false)               &&
236*c8dee2aaSAndroid Build Coastguard Worker                         max(a, b)              == half4(2, 2, 1, 1)                &&
237*c8dee2aaSAndroid Build Coastguard Worker                         max(c, d)              == int3(1111, 5555, 5555)           &&
238*c8dee2aaSAndroid Build Coastguard Worker                         max(e, f)              == uint2(3333333333u, 222)          &&
239*c8dee2aaSAndroid Build Coastguard Worker                         max(a, 1)              == half4(1, 2, 1, 1)                &&
240*c8dee2aaSAndroid Build Coastguard Worker                         max(c, 3333)           == int3(3333, 3333, 5555)           &&
241*c8dee2aaSAndroid Build Coastguard Worker                         max(e, 7777)           == uint2(1111111111u, 7777)         &&
242*c8dee2aaSAndroid Build Coastguard Worker                         min(a, b)              == half4(1, 2, 0, 0)                &&
243*c8dee2aaSAndroid Build Coastguard Worker                         min(c, d)              == int3(1111, 3333, 3333)           &&
244*c8dee2aaSAndroid Build Coastguard Worker                         min(e, f)              == uint2(1111111111u, 222)          &&
245*c8dee2aaSAndroid Build Coastguard Worker                         min(a, 1)              == half4(1, 1, 0, 1)                &&
246*c8dee2aaSAndroid Build Coastguard Worker                         min(c, 3333)           == int3(1111, 3333, 3333)           &&
247*c8dee2aaSAndroid Build Coastguard Worker                         min(e, 7777)           == uint2(7777, 222)) ? colorGreen : colorRed;
248*c8dee2aaSAndroid Build Coastguard Worker             }
249*c8dee2aaSAndroid Build Coastguard Worker          )__SkSL__",
250*c8dee2aaSAndroid Build Coastguard Worker          /*uniforms=*/{},
251*c8dee2aaSAndroid Build Coastguard Worker          /*startingColor=*/SkColor4f{0.0, 0.0, 0.0, 0.0},
252*c8dee2aaSAndroid Build Coastguard Worker          /*expectedResult=*/SkColor4f{0.0, 1.0, 0.0, 1.0});
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(SkSLRasterPipelineSlotOverflow_355465305,r)255*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(SkSLRasterPipelineSlotOverflow_355465305, r) {
256*c8dee2aaSAndroid Build Coastguard Worker     constexpr int kStructMembers1 = 6200;
257*c8dee2aaSAndroid Build Coastguard Worker     constexpr int kStructMembers2 = 433;
258*c8dee2aaSAndroid Build Coastguard Worker     std::stringstream str;
259*c8dee2aaSAndroid Build Coastguard Worker     str << "struct M { float4x4 m";
260*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 1; i < kStructMembers1; ++i) {
261*c8dee2aaSAndroid Build Coastguard Worker         str << ",m" << i;
262*c8dee2aaSAndroid Build Coastguard Worker     }
263*c8dee2aaSAndroid Build Coastguard Worker     str << ";};";
264*c8dee2aaSAndroid Build Coastguard Worker     str << "struct M2 { float4x4 m";
265*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 1; i < kStructMembers2; ++i) {
266*c8dee2aaSAndroid Build Coastguard Worker         str << ",m" << i;
267*c8dee2aaSAndroid Build Coastguard Worker     }
268*c8dee2aaSAndroid Build Coastguard Worker     str << ";};";
269*c8dee2aaSAndroid Build Coastguard Worker     str << "M f() { M m; return m; }";
270*c8dee2aaSAndroid Build Coastguard Worker     constexpr int kConstMembers = 40;
271*c8dee2aaSAndroid Build Coastguard Worker     str << "struct T { float4x4 m0";
272*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 1; i < kConstMembers; ++i) {
273*c8dee2aaSAndroid Build Coastguard Worker         str << ",m" << i;
274*c8dee2aaSAndroid Build Coastguard Worker     }
275*c8dee2aaSAndroid Build Coastguard Worker     str << ";};";
276*c8dee2aaSAndroid Build Coastguard Worker     str << "const T K = T(";
277*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < kConstMembers; ++i) {
278*c8dee2aaSAndroid Build Coastguard Worker         if (i > 0) {
279*c8dee2aaSAndroid Build Coastguard Worker             str << ",";
280*c8dee2aaSAndroid Build Coastguard Worker         }
281*c8dee2aaSAndroid Build Coastguard Worker         str << "mat4x4(1337)";
282*c8dee2aaSAndroid Build Coastguard Worker     }
283*c8dee2aaSAndroid Build Coastguard Worker     str << ");";
284*c8dee2aaSAndroid Build Coastguard Worker     str << "half4 main(half4 color) {";
285*c8dee2aaSAndroid Build Coastguard Worker     str << "float4x4 a = M2(";
286*c8dee2aaSAndroid Build Coastguard Worker     for (int j = 0; j < kStructMembers2; ++j) {
287*c8dee2aaSAndroid Build Coastguard Worker         if (j > 0) {
288*c8dee2aaSAndroid Build Coastguard Worker             str << ",";
289*c8dee2aaSAndroid Build Coastguard Worker         }
290*c8dee2aaSAndroid Build Coastguard Worker         const int numAddOps = (j == kStructMembers1 - 1) ? 23 : 25;
291*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < numAddOps; ++i) {
292*c8dee2aaSAndroid Build Coastguard Worker             if (i > 0) {
293*c8dee2aaSAndroid Build Coastguard Worker                 str << "+";
294*c8dee2aaSAndroid Build Coastguard Worker             }
295*c8dee2aaSAndroid Build Coastguard Worker             str << "f().m";
296*c8dee2aaSAndroid Build Coastguard Worker         }
297*c8dee2aaSAndroid Build Coastguard Worker     }
298*c8dee2aaSAndroid Build Coastguard Worker     str << ").m;";
299*c8dee2aaSAndroid Build Coastguard Worker     str << "return half4(a[0]+(K.m0+K.m1+K.m2+K.m3)[0]);";
300*c8dee2aaSAndroid Build Coastguard Worker     str << "}";
301*c8dee2aaSAndroid Build Coastguard Worker     std::string src = str.str();
302*c8dee2aaSAndroid Build Coastguard Worker 
303*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Compiler compiler;
304*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkSL::Program> program =
305*c8dee2aaSAndroid Build Coastguard Worker             compiler.convertProgram(SkSL::ProgramKind::kRuntimeColorFilter, src, {});
306*c8dee2aaSAndroid Build Coastguard Worker     if (!program) {
307*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "Unexpected error compiling %s\n%s", src.c_str(), compiler.errorText().c_str());
308*c8dee2aaSAndroid Build Coastguard Worker         return;
309*c8dee2aaSAndroid Build Coastguard Worker     }
310*c8dee2aaSAndroid Build Coastguard Worker     const SkSL::FunctionDeclaration* main = program->getFunction("main");
311*c8dee2aaSAndroid Build Coastguard Worker     if (!main) {
312*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "Program must have a 'main' function");
313*c8dee2aaSAndroid Build Coastguard Worker         return;
314*c8dee2aaSAndroid Build Coastguard Worker     }
315*c8dee2aaSAndroid Build Coastguard Worker     SkArenaAlloc alloc(1000);
316*c8dee2aaSAndroid Build Coastguard Worker     SkRasterPipeline pipeline(&alloc);
317*c8dee2aaSAndroid Build Coastguard Worker     pipeline.appendConstantColor(&alloc, SkColors::kWhite);
318*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkSL::RP::Program> rasterProg =
319*c8dee2aaSAndroid Build Coastguard Worker             SkSL::MakeRasterPipelineProgram(*program, *main->definition());
320*c8dee2aaSAndroid Build Coastguard Worker     // Ideally, this program would fail in the front-end, because of the number of slots needed
321*c8dee2aaSAndroid Build Coastguard Worker     // for expression evaluation. For now, it succeeds (but then fails in appendStages).
322*c8dee2aaSAndroid Build Coastguard Worker     if (!rasterProg) {
323*c8dee2aaSAndroid Build Coastguard Worker         ERRORF(r, "MakeRasterPipelineProgram failed");
324*c8dee2aaSAndroid Build Coastguard Worker         return;
325*c8dee2aaSAndroid Build Coastguard Worker     }
326*c8dee2aaSAndroid Build Coastguard Worker 
327*c8dee2aaSAndroid Build Coastguard Worker     // Append the SkSL program to the raster pipeline.
328*c8dee2aaSAndroid Build Coastguard Worker     bool success = rasterProg->appendStages(&pipeline, &alloc, /*callbacks=*/nullptr, {});
329*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(r, !success, "appendStages should fail for very large program");
330*c8dee2aaSAndroid Build Coastguard Worker }
331