61#include <initializer_list>
73#if defined(SK_GRAPHITE)
95 "Expected error message to contain \"%s\". Actual message: \"%s\"",
96 expected, errorText.c_str());
99#define EMPTY_MAIN "half4 main(float2 p) { return half4(0); }"
109DEF_TEST(SkRuntimeEffectInvalid_UndefinedFunction, r) {
111 "function 'half4 missing()' is not defined");
119DEF_TEST(SkRuntimeEffectInvalid_SkCapsDisallowed, r) {
123 "half4 main(float2 p) { return sk_Caps.floatIs32Bits ? half4(1) : half4(0); }",
124 "name 'sk_Caps' is reserved");
127DEF_TEST(SkRuntimeEffect_DeadCodeEliminationStackOverflow, r) {
130 half4 main(half4 color) {
131 half value = color.r;
133 for (int a=0; a<10; ++a) { // 10
134 for (int b=0; b<10; ++b) { // 100
135 for (int c=0; c<10; ++c) { // 1000
136 for (int d=0; d<10; ++d) { // 10000
146DEF_TEST(SkRuntimeEffectCanDisableES2Restrictions, r) {
154 test_valid_es3 (r,
"float f[2] = float[2](0, 1);" EMPTY_MAIN);
164 "construction of array type");
165 test_valid (r,
"#version 300\nfloat f[2] = float[2](0, 1);" EMPTY_MAIN);
170 uniform int simple; // should have no flags
171 uniform float arrayOfOne[1]; // should have kArray_Flag
172 uniform float arrayOfMultiple[2]; // should have kArray_Flag
173 layout(color) uniform float4 color; // should have kColor_Flag
174 uniform half3 halfPrecisionFloat; // should have kHalfPrecision_Flag
175 layout(color) uniform half4 allFlags[2]; // should have Array | Color | HalfPrecision
206 auto test_valid = [r](
const char* sksl) {
211 auto test_invalid = [r](
const char* sksl,
const char* expected) {
215 errorText.contains(expected),
216 "Expected error message to contain \"%s\". Actual message: \"%s\"",
222 test_valid(
"half4 main(half4 c) { return c; }");
223 test_valid(
"float4 main(half4 c) { return c; }");
224 test_valid(
"half4 main(float4 c) { return c; }");
225 test_valid(
"float4 main(float4 c) { return c; }");
226 test_valid(
"vec4 main(half4 c) { return c; }");
227 test_valid(
"half4 main(vec4 c) { return c; }");
228 test_valid(
"vec4 main(vec4 c) { return c; }");
231 test_invalid(
"void main(half4 c) {}",
"'main' must return");
232 test_invalid(
"half3 main(half4 c) { return c.rgb; }",
"'main' must return");
235 test_invalid(
"half4 main() { return half4(1); }",
"'main' parameter");
236 test_invalid(
"half4 main(float2 p) { return half4(1); }",
"'main' parameter");
237 test_invalid(
"half4 main(float2 p, half4 c) { return c; }",
"'main' parameter");
240 test_invalid(
"half4 main(half4 c) { return sk_FragCoord.xy01; }",
"unknown identifier");
243 test_valid(
"uniform shader child;"
244 "half4 main(half4 c) { return child.eval(c.rg); }");
247 test_valid(
"uniform colorFilter child;"
248 "half4 main(half4 c) { return child.eval(c); }");
251 test_valid(
"uniform blender child;"
252 "half4 main(half4 c) { return child.eval(c, c); }");
257 auto test_valid = [r](
const char* sksl) {
262 auto test_invalid = [r](
const char* sksl,
const char* expected) {
266 errorText.contains(expected),
267 "Expected error message to contain \"%s\". Actual message: \"%s\"",
274 test_valid(
"half4 main(half4 s, half4 d) { return s; }");
275 test_valid(
"float4 main(float4 s, float4 d) { return d; }");
276 test_valid(
"float4 main(half4 s, float4 d) { return s; }");
277 test_valid(
"half4 main(float4 s, half4 d) { return d; }");
278 test_valid(
"vec4 main(half4 s, half4 d) { return s; }");
279 test_valid(
"half4 main(vec4 s, vec4 d) { return d; }");
280 test_valid(
"vec4 main(vec4 s, vec4 d) { return s; }");
283 test_invalid(
"void main(half4 s, half4 d) {}",
"'main' must return");
284 test_invalid(
"half3 main(half4 s, half4 d) { return s.rgb; }",
"'main' must return");
287 test_invalid(
"half4 main() { return half4(1); }",
"'main' parameter");
288 test_invalid(
"half4 main(half4 c) { return c; }",
"'main' parameter");
289 test_invalid(
"half4 main(float2 p) { return half4(1); }",
"'main' parameter");
290 test_invalid(
"half4 main(float2 p, half4 c) { return c; }",
"'main' parameter");
291 test_invalid(
"half4 main(float2 p, half4 a, half4 b) { return a; }",
"'main' parameter");
292 test_invalid(
"half4 main(half4 a, half4 b, half4 c) { return a; }",
"'main' parameter");
295 test_invalid(
"half4 main(half4 s, half4 d) { return sk_FragCoord.xy01; }",
296 "unknown identifier");
299 test_valid(
"uniform shader child;"
300 "half4 main(half4 s, half4 d) { return child.eval(s.rg); }");
303 test_valid(
"uniform colorFilter child;"
304 "half4 main(half4 s, half4 d) { return child.eval(d); }");
307 test_valid(
"uniform blender child;"
308 "half4 main(half4 s, half4 d) { return child.eval(s, d); }");
319 const char* expected,
324 errorText.contains(expected),
325 "Expected error message to contain \"%s\". Actual message: \"%s\"",
332 test_valid(
"half4 main(float2 p) { return p.xyxy; }");
333 test_valid(
"float4 main(float2 p) { return p.xyxy; }");
334 test_valid(
"vec4 main(float2 p) { return p.xyxy; }");
335 test_valid(
"half4 main(vec2 p) { return p.xyxy; }");
336 test_valid(
"vec4 main(vec2 p) { return p.xyxy; }");
342 test_invalid(
"half4 main(float2 p, half4 c) { return c; }",
"'main' parameter");
345 test_invalid(
"half4 main(float2 p, float4 c) { return c; }",
"'main' parameter");
348 test_invalid(
"half4 main(float2 p, vec4 c) { return c; }",
"'main' parameter");
351 test_invalid(
"float4 main(float2 p, half4 c) { return c; }",
"'main' parameter");
354 test_invalid(
"vec4 main(float2 p, half4 c) { return c; }",
"'main' parameter");
357 test_invalid(
"vec4 main(vec2 p, vec4 c) { return c; }",
"'main' parameter");
361 test_invalid(
"void main(float2 p) {}",
"'main' must return");
362 test_invalid(
"half3 main(float2 p) { return p.xy1; }",
"'main' must return");
365 test_invalid(
"half4 main() { return half4(1); }",
"'main' parameter");
366 test_invalid(
"half4 main(half4 c) { return c; }",
"'main' parameter");
369 test_invalid(
"half4 main(float2 p) { return sk_FragCoord.xy01; }",
370 "unknown identifier 'sk_FragCoord'");
372 test_valid(
"half4 main(float2 p) { return sk_FragCoord.xy01; }",
options);
375 test_valid(
"uniform shader child;"
376 "half4 main(float2 p) { return child.eval(p); }");
379 test_valid(
"uniform colorFilter child;"
380 "half4 main(float2 p) { return child.eval(half4(1)); }");
383 test_valid(
"uniform blender child;"
384 "half4 main(float2 p) { return child.eval(half4(0.5), half4(0.6)); }");
391 if (preTestCallback) {
392 preTestCallback(canvas,
paint);
408 std::array<GrColor, 4> expected) {
409 std::array<GrColor, 4> actual;
416 if (actual != expected) {
419 "Expected: [ %08x %08x %08x %08x ]\n"
420 "Got : [ %08x %08x %08x %08x ]\n"
422 expected[0], expected[1], expected[2], expected[3],
423 actual[0], actual[1], actual[2], actual[3],
424 effect->
source().c_str()));
434#if defined(SK_GRAPHITE)
437 }
else if (grContext) {
452 : fReporter(r), fGrContext(grContext), fGraphite(graphite), fSize(
size) {
461 ERRORF(fReporter,
"Effect didn't compile: %s", errorText.c_str());
464 fBuilder.
init(std::move(effect));
475 void test(std::array<GrColor, 4> expected,
PreTestFn preTestCallback =
nullptr) {
478 ERRORF(fReporter,
"Effect didn't produce a shader");
492 paint.setShader(std::move(shader));
503 ERRORF(fReporter,
"Effect didn't produce a shader");
511 paint.setShader(std::move(debugShader));
517 debugTrace->dump(&wstream);
519 return std::string(
static_cast<const char*
>(streamData->
data()), streamData->
size());
523 this->
test({expected, expected, expected, expected}, preTestCallback);
538 : fReporter(r), fGrContext(grContext), fGraphite(graphite) {
545 ERRORF(fReporter,
"Effect didn't compile: %s", errorText.c_str());
548 fBuilder.
init(std::move(effect));
552 return fSurface.
get();
563 void test(std::array<GrColor, 4> expected,
PreTestFn preTestCallback =
nullptr) {
566 ERRORF(fReporter,
"Effect didn't produce a blender");
572 paint.setBlender(std::move(blender));
581 this->
test({expected, expected, expected, expected}, preTestCallback);
600 static constexpr SkScalar pos[] = { 0, .25f, .25f, .50f, .50f, .75, .75, 1 };
609 using float4 = std::array<float, 4>;
610 using int4 = std::array<int, 4>;
613 effect.
build(
"half4 main(float2 p) { return half4(half2(p - 0.5), 0, 1); }");
614 effect.
test({0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF});
617 effect.
build(
"uniform float4 gColor; half4 main(float2 p) { return half4(gColor); }");
618 effect.
uniform(
"gColor") =
float4{ 0.0f, 0.25f, 0.75f, 1.0f };
619 effect.
test(0xFFBF4000);
620 effect.
uniform(
"gColor") =
float4{ 1.0f, 0.0f, 0.0f, 0.498f };
621 effect.
test(0x7F0000FF);
624 effect.
build(
"uniform int4 gColor; half4 main(float2 p) { return half4(gColor) / 255.0; }");
625 effect.
uniform(
"gColor") =
int4{ 0x00, 0x40, 0xBF, 0xFF };
626 effect.
test(0xFFBF4000);
627 effect.
uniform(
"gColor") =
int4{ 0xFF, 0x00, 0x00, 0x7F };
628 effect.
test(0x7F0000FF);
634 "half4 main(float2 p) { return half4(0.498 * (half2(sk_FragCoord.xy) - 0.5), 0, 1); }");
635 effect.
test({0xFF000000, 0xFF00007F, 0xFF007F00, 0xFF007F7F},
639 effect.
build(
"half4 main(float2 p) { return float4(p - 0.5, 0, 1); }");
640 effect.
test({0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF});
643 effect.
build(
"float4 main(float2 p) { return float4(p - 0.5, 0, 1); }");
644 effect.
test({0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF});
645 effect.
build(
"vec4 main(float2 p) { return float4(p - 0.5, 0, 1); }");
646 effect.
test({0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF});
649 effect.
build(
"vec4 main(vec2 p) { p -= 0.5; return vec4(p, 0, 1); }");
650 effect.
test({0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF});
651 effect.
build(
"void moveCoords(inout vec2 p) { p -= 0.5; }"
652 "vec4 main(vec2 p) { moveCoords(p); return vec4(p, 0, 1); }");
653 effect.
test({0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF});
662 effect.
build(
"uniform shader child;"
663 "half4 main(float2 p) { return child.eval(p); }");
664 effect.
child(
"child") =
nullptr;
665 effect.
test(0x00000000,
670 effect.
build(
"uniform colorFilter child;"
671 "half4 main(float2 p) { return child.eval(half4(1, 1, 0, 1)); }");
672 effect.
child(
"child") =
nullptr;
673 effect.
test(0xFF00FFFF);
676 effect.
build(
"uniform blender child;"
677 "half4 main(float2 p) {"
678 " float4 src = float4(p - 0.5, 0, 1) * 0.498;"
679 " return child.eval(src, half4(0, 0, 0, 1));"
681 effect.
child(
"child") =
nullptr;
682 effect.
test({0xFF000000, 0xFF00007F, 0xFF007F00, 0xFF007F7F});
687 effect.
build(
"uniform shader child;"
688 "half4 main(float2 p) { return child.eval(p); }");
689 effect.
child(
"child") = rgbwShader;
690 effect.
test({0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFFFFFF});
693 effect.
build(
"uniform shader child;"
694 "half4 main(float2 p) { return child.eval(p.yx); }");
695 effect.
child(
"child") = rgbwShader;
696 effect.
test({0xFF0000FF, 0xFFFF0000, 0xFF00FF00, 0xFFFFFFFF});
700 effect.
build(
"uniform shader child;"
701 "half4 main(float2 p) { return half4(0, 1, 0, 1); }");
702 effect.
child(
"child") = rgbwShader;
703 effect.
test(0xFF00FF00);
710 effect.
build(
"float2 helper(float2 x) { return x + 1; }"
711 "half4 main(float2 p) { float2 v = helper(p); return half4(half2(v), 0, 1); }");
712 effect.
test(0xFF00FFFF);
719#if defined(SK_GRAPHITE)
722 std::unique_ptr<skgpu::graphite::Recorder> recorder = context->makeRecorder();
772 half4 main(float2 xy) { return half4(0, 1, 0, 1); }
776 paint.setShader(effect->makeShader(nullptr, {}));
788 half4 main(float2 xy) {
789 half4 result = half4(0, 1, 0, 1);
790 result.g = intBitsToFloat(floatBitsToInt(result.g));
796 paint.setShader(effect->makeShader(nullptr, {}));
808 half4 main(half4 src, half4 dst) { return half4(0, 1, 0, 1); }
812 paint.setBlender(effect->makeBlender(nullptr, {}));
820 half4 main(half4 src, half4 dst) {
821 half4 result = half4(0, 1, 0, 1);
822 result.g = intBitsToFloat(floatBitsToInt(result.g));
828 paint.setBlender(effect->makeBlender(nullptr, {}));
862 half4 main(half4 color) { return half4(2); }
866 paint.setColorFilter(effect->makeColorFilter(nullptr));
878 half4 main(half4 inColor) { return half4(1, 0, 0, 1); }
887 half4 main(half4 inColor) {
888 half4 result = half4(1, 0, 0, 1);
889 for (int i = 0; i < loops; i++) {
890 result = result.argb;
900 for (
int imageSize : {2, 80}) {
902 SkISize{imageSize, imageSize});
904 half4 main(float2 p) {
905 float2 val = p - 0.5;
909 int center = imageSize / 2;
911 static constexpr char kSkRPSlotDump[] =
912R
"($0 = p (float2 : slot 1/2, L0)
913$1 = p (float2 : slot 2/2, L0)
914$2 = [main].result (float4 : slot 1/4, L0)
915$3 = [main].result (float4 : slot 2/4, L0)
916$4 = [main].result (float4 : slot 3/4, L0)
917$5 = [main].result (float4 : slot 4/4, L0)
918$6 = val (float2 : slot 1/2, L0)
919$7 = val (float2 : slot 2/2, L0)
920F0 = half4 main(float2 p)
923enter half4 main(float2 p)
936exit half4 main(float2 p)
941 "Trace does not match expectation for %dx%d:\n%.*s\n",
942 imageSize, imageSize, (
int)
dump.size(),
dump.data());
946DEF_TEST(SkRuntimeEffectTracesAreUnoptimized, r) {
950 int globalUnreferencedVar = 7;
951 half inlinableFunction() {
954 half4 main(float2 p) {
956 int localUnreferencedVar = 7;
958 return inlinableFunction().xxxx;
961 std::string dump = effect.trace({1, 1});
962 static constexpr char kSkRPSlotDump[] =
963R
"($0 = p (float2 : slot 1/2, L0)
964$1 = p (float2 : slot 2/2, L0)
965$2 = globalUnreferencedVar (int, L0)
966$3 = [main].result (float4 : slot 1/4, L0)
967$4 = [main].result (float4 : slot 2/4, L0)
968$5 = [main].result (float4 : slot 3/4, L0)
969$6 = [main].result (float4 : slot 4/4, L0)
970$7 = localUnreferencedVar (int, L0)
971$8 = [inlinableFunction].result (float, L0)
972F0 = half4 main(float2 p)
973F1 = half inlinableFunction()
975 static constexpr char kExpectedTrace[] = R
"(
976globalUnreferencedVar = 7
977enter half4 main(float2 p)
984 localUnreferencedVar = 7
987 enter half inlinableFunction()
990 [inlinableFunction].result = 1
992 exit half inlinableFunction()
998exit half4 main(float2 p)
1003 "Trace output does not match expectation:\n%.*s\n", (
int)
dump.size(),
dump.data());
1006DEF_TEST(SkRuntimeEffectTraceCodeThatCannotBeUnoptimized, r) {
1010 half4 main(float2 p) {
1011 int variableThatGetsOptimizedAway = 7;
1015 // This (unreachable) path doesn't return a value.
1016 // Without optimization, SkSL thinks this code doesn't return a value on every path.
1019 std::string dump = effect.trace({1, 1});
1020 static constexpr char kSkRPSlotDump[] =
1021R
"($0 = p (float2 : slot 1/2, L0)
1022$1 = p (float2 : slot 2/2, L0)
1023$2 = [main].result (float4 : slot 1/4, L0)
1024$3 = [main].result (float4 : slot 2/4, L0)
1025$4 = [main].result (float4 : slot 3/4, L0)
1026$5 = [main].result (float4 : slot 4/4, L0)
1027F0 = half4 main(float2 p)
1029 static constexpr char kExpectedTrace[] = R
"(
1030enter half4 main(float2 p)
1042exit half4 main(float2 p)
1047 "Trace output does not match expectation:\n%.*s\n", (
int)
dump.size(),
dump.data());
1053 TestBlend effect(r, grContext, graphite);
1055 using float2 = std::array<float, 2>;
1056 using float4 = std::array<float, 4>;
1057 using int4 = std::array<int, 4>;
1060 effect.build(
"uniform float4 gColor; half4 main(half4 s, half4 d) { return half4(gColor); }");
1061 effect.uniform(
"gColor") =
float4{ 0.0f, 0.25f, 0.75f, 1.0f };
1062 effect.test(0xFFBF4000);
1063 effect.uniform(
"gColor") =
float4{ 1.0f, 0.0f, 0.0f, 0.498f };
1064 effect.test(0x7F0000FF);
1067 effect.build(
"uniform int4 gColor;"
1068 "half4 main(half4 s, half4 d) { return half4(gColor) / 255.0; }");
1069 effect.uniform(
"gColor") =
int4{ 0x00, 0x40, 0xBF, 0xFF };
1070 effect.test(0xFFBF4000);
1071 effect.uniform(
"gColor") =
int4{ 0xFF, 0x00, 0x00, 0x7F };
1072 effect.test(0x7F0000FF);
1075 effect.build(
"half4 main(half4 s, half4 d) { s += d; d += s; return half4(1); }");
1076 effect.test(0xFFFFFFFF);
1080 effect.build(
"half4 main(half4 s, half4 d) { return s; }");
1081 effect.test(0xFF888888);
1087 effect.surface()->getCanvas()->drawPaint(rgbwPaint);
1091 effect.build(
"half4 main(half4 s, half4 d) { return d; }");
1092 effect.test({0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFFFFFF});
1096 effect.build(
"half4 main(half4 s, half4 d) { return half4(1) - d; }");
1097 effect.test({0x00FFFF00, 0x00FF00FF, 0x0000FFFF, 0x00000000});
1100 effect.build(
"half4 main(half4 s, half4 d) { return half4(-1); }");
1101 effect.test(0x00000000);
1102 effect.build(
"half4 main(half4 s, half4 d) { return half4(2); }");
1103 effect.test(0xFFFFFFFF);
1110 effect.build(
"uniform shader child;"
1111 "half4 main(half4 s, half4 d) { return child.eval(s.rg); }");
1112 effect.child(
"child") =
nullptr;
1113 effect.test(0x00000000,
1116 effect.build(
"uniform colorFilter child;"
1117 "half4 main(half4 s, half4 d) { return child.eval(s); }");
1118 effect.child(
"child") =
nullptr;
1119 effect.test(0xFF00FFFF,
1123 effect.surface()->getCanvas()->drawPaint(rgbwPaint);
1124 effect.build(
"uniform blender child;"
1125 "half4 main(half4 s, half4 d) { return child.eval(s, d); }");
1126 effect.child(
"child") =
nullptr;
1127 effect.test({0xFF000080, 0xFF008000, 0xFF800000, 0xFF808080},
1131 effect.build(
"uniform shader child;"
1132 "uniform half2 pos;"
1133 "half4 main(half4 s, half4 d) { return child.eval(pos); }");
1135 effect.uniform(
"pos") =
float2{0.5, 0.5};
1136 effect.test(0xFF0000FF);
1138 effect.uniform(
"pos") =
float2{1.5, 0.5};
1139 effect.test(0xFF00FF00);
1141 effect.uniform(
"pos") =
float2{0.5, 1.5};
1142 effect.test(0xFFFF0000);
1144 effect.uniform(
"pos") =
float2{1.5, 1.5};
1145 effect.test(0xFFFFFFFF);
1148 effect.build(
"uniform colorFilter child;"
1149 "half4 main(half4 s, half4 d) { return child.eval(half4(1)); }");
1151 effect.test(0xFF452301);
1154 effect.surface()->getCanvas()->drawPaint(rgbwPaint);
1155 effect.build(
"uniform blender child;"
1156 "half4 main(half4 s, half4 d) { return child.eval(s, d); }");
1158 effect.test({0xFF4523FF, 0xFF45FF01, 0xFFFF2301, 0xFFFFFFFF},
1162 effect.surface()->getCanvas()->drawPaint(rgbwPaint);
1163 effect.build(
"uniform blender child;"
1164 "half4 main(half4 s, half4 d) { return child.eval(s, d); }");
1166 effect.test({0xFF4523FF, 0xFF45FF01, 0xFFFF2301, 0xFFFFFFFF},
1170DEF_TEST(SkRuntimeEffect_Blender_CPU, r) {
1181DEF_TEST(SkRuntimeShaderBuilderReuse, r) {
1184 half4 main(float2 p) { return half4(x); }
1192 b.uniform(
"x") = 0.0f;
1193 auto shader_0 =
b.makeShader();
1195 b.uniform(
"x") = 1.0f;
1196 auto shader_1 =
b.makeShader();
1199DEF_TEST(SkRuntimeBlendBuilderReuse, r) {
1202 half4 main(half4 s, half4 d) { return half4(x); }
1210 for (
float x = 0.0f;
x <= 2.0f;
x += 2.0f) {
1216DEF_TEST(SkRuntimeShaderBuilderSetUniforms, r) {
1217 const char* kSource = R
"(
1219 uniform vec2 offset;
1220 half4 main(float2 p) { return half4(x); }
1233 float origin[] = { 2.0f, 3.0f, 4.0f };
1241 auto shader =
b.makeShader();
1244DEF_TEST(SkRuntimeEffectThreaded, r) {
1248 static constexpr char kSource[] =
"half4 main(float2 p) { return sk_FragCoord.xyxy; }";
1250 std::thread threads[16];
1251 for (
auto& thread : threads) {
1252 thread = std::thread([r]() {
1260 for (
auto& thread : threads) {
1265DEF_TEST(SkRuntimeEffectAllowsPrivateAccess, r) {
1272 static constexpr char kShader[] =
1273 "half4 main(float2 p) { return $hsl_to_rgb(p.xxx, p.y); }";
1285 "half4 main(half4 c) { return $hsl_to_rgb(c.rgb, c.a); }";
1296 static constexpr char kBlender[] =
1297 "half4 main(half4 s, half4 d) { return $hsl_to_rgb(s.rgb, d.a); }";
1307DEF_TEST(SkRuntimeColorFilterSingleColor, r) {
1309 auto [effect, err] =
1328 "uniform shader paint;"
1329 "struct S { half4 rgba; };"
1330 "void process(inout S s) { s.rgba.rgb *= 0.5; }"
1331 "half4 main(float2 p) { S s; s.rgba = paint.eval(p); process(s); return s.rgba; }"
1342 "uniform shader child;"
1343 "struct S { float2 coord; };"
1344 "void process(inout S s) { s.coord = s.coord.yx; }"
1345 "half4 main(float2 p) { S s; s.coord = p; process(s); return child.eval(s.coord); "
1347 effect.child(
"child") = child;
1351DEF_TEST(SkRuntimeStructNameReuse, r) {
1362DEF_TEST(SkRuntimeColorFilterFlags, r) {
1363 auto expectAlphaUnchanged = [&](
const char* shader) {
1370 auto expectAlphaChanged = [&](
const char* shader) {
1378 expectAlphaUnchanged(
"half4 main(half4 color) { return color; }");
1379 expectAlphaUnchanged(
"half4 main(half4 color) { return color.aaaa; }");
1380 expectAlphaUnchanged(
"half4 main(half4 color) { return color.bgra; }");
1381 expectAlphaUnchanged(
"half4 main(half4 color) { return color.rraa; }");
1382 expectAlphaUnchanged(
"half4 main(half4 color) { return color.010a; }");
1383 expectAlphaUnchanged(
"half4 main(half4 color) { return half4(0, 0, 0, color.a); }");
1384 expectAlphaUnchanged(
"half4 main(half4 color) { return half4(half2(1), color.ba); }");
1385 expectAlphaUnchanged(
"half4 main(half4 color) { return half4(half2(1), half2(color.a)); }");
1386 expectAlphaUnchanged(
"half4 main(half4 color) { return half4(color.a); }");
1387 expectAlphaUnchanged(
"half4 main(half4 color) { return half4(float4(color.baba)); }");
1388 expectAlphaUnchanged(
"half4 main(half4 color) { return color.r != color.g ? color :"
1390 expectAlphaUnchanged(
"half4 main(half4 color) { return color.a == color.r ? color.rrra : "
1391 "color.g == color.b ? color.ggga : "
1394 expectAlphaChanged(
"half4 main(half4 color) { color.a = 0; return color; }");
1397 expectAlphaChanged(
"half4 main(half4 color) { return color.argb; }");
1398 expectAlphaChanged(
"half4 main(half4 color) { return color.rrrr; }");
1401 expectAlphaChanged(
"half4 main(half4 color) { return half4(1, 1, 1, color.r); }");
1404 expectAlphaChanged(
"half4 main(half4 color) { return half4(color.r); }");
1407 expectAlphaChanged(
"half4 main(half4 color) { return color.a > 0 ? half4(0) : color; }");
1408 expectAlphaChanged(
"half4 main(half4 color) { return color.g < 1 ? color.bgra : color.abgr; }");
1409 expectAlphaChanged(
"half4 main(half4 color) { return color.b > 0.5 ? half4(0) : half4(1); }");
1413 expectAlphaChanged(
"half4 main(half4 color) { return color + half4(1,1,1,0); }");
1414 expectAlphaChanged(
"half4 main(half4 color) { return color + half4(0,0,0,4); }");
1417 expectAlphaChanged(
"half4 main(half4 color) { "
1418 " if (color.r > 0.5) { return color; }"
1421 expectAlphaChanged(
"half4 main(half4 color) { "
1422 " if (color.r > 0.5) { return half4(0); }"
1427DEF_TEST(SkRuntimeShaderSampleCoords, r) {
1435 auto test = [&](
const char*
src,
bool expectExplicit,
bool expectReferencesSampleCoords) {
1436 auto [effect, err] =
1445 REPORTER_ASSERT(r,
fp->childProcessor(0)->sampleUsage().isExplicit() == expectExplicit);
1453 test(
"half4 main(float2 xy) { return child.eval(xy); }",
false,
false);
1455 test(
"half4 main(float2 xy) { return child.eval(xy) + sin(xy.x); }",
false,
true);
1460 test(
"half4 main(float2 xy) { return child.eval(float2(0, 0)); }",
true,
false);
1462 test(
"half4 main(float2 xy) { return child.eval(xy * 0.5); }",
true,
true);
1464 test(
"half4 main(float2 xy) { xy *= 2; return child.eval(xy); }",
true,
true);
1466 test(
"void adjust(inout float2 xy) { xy *= 2; }"
1467 "half4 main(float2 xy) { adjust(xy); return child.eval(xy); }",
true,
true);
1473 test(
"half4 main(float2 xy) { half4 c = child.eval(xy); xy *= 2; return c; }",
true,
true);
1475 test(
"half4 main(float2 xy) { float2 p = xy; return child.eval(p); }",
true,
true);
1477 test(
"half4 helper(float2 xy) { return child.eval(xy); }"
1478 "half4 main(float2 xy) { return helper(xy); }",
true,
true);
1481DEF_TEST(SkRuntimeShaderIsOpaque, r) {
1486 auto test = [&](
const char* body,
bool expectOpaque) {
1488 uniform shader cOnes;
1489 uniform shader cZeros;
1490 uniform float4 uOnes;
1491 uniform float4 uZeros;
1492 half4 main(float2 xy) {
1503 builder.child(
"cOnes") = std::move(cOnes);
1504 builder.child(
"cZeros") = std::move(cZeros);
1508 auto shader =
builder.makeShader();
1515 test(
"return half4(1);",
true);
1516 test(
"return half4(0, 1, 0, 1);",
true);
1517 test(
"return half4(0, 0, 0, 1);",
true);
1520 test(
"return uZeros.rgb1;",
true);
1521 test(
"return uZeros.bgra.rgb1;",
true);
1522 test(
"return half4(uZeros.rgb, 1);",
true);
1525 test(
"return cZeros.eval(xy).rgb1;",
true);
1526 test(
"return cZeros.eval(xy).bgra.rgb1;",
true);
1527 test(
"return half4(cZeros.eval(xy).rgb, 1);",
true);
1530 test(
"if (xy.x < 100) { return uZeros.rgb1; } else { return cZeros.eval(xy).rgb1; }",
true);
1533 test(
"return (cZeros.eval(xy) * uZeros).rgb1;",
true);
1534 test(
"return half4(1, 1, 1, 0.5 + 0.5);",
true);
1537 test(
"const half4 kWhite = half4(1); return kWhite;",
true);
1542 test(
"return half4(0);",
false);
1543 test(
"return half4(1, 1, 1, 0);",
false);
1546 test(
"return uZeros;",
false);
1547 test(
"return cZeros.eval(xy);",
false);
1550 test(
"if (xy.x < 100) { return uZeros; } else { return cZeros.eval(xy).rgb1; }",
false);
1551 test(
"if (xy.x < 100) { return uZeros.rgb1; } else { return cZeros.eval(xy); }",
false);
1557 test(
"return xy.x < 100 ? uZeros.rgb1 : cZeros.eval(xy).rgb1;",
false);
1562 test(
"return uOnes;",
false);
1563 test(
"return cOnes.eval(xy);",
false);
1568 std::unique_ptr<GrFragmentProcessor>
fp;
1576 "uniform half4 color;"
1577 "half4 main(float2 xy) { return color; }"
1584 result.fp->addToKey(*ctxInfo.directContext()->priv().caps()->shaderCaps(), &
builder);
1589 FpAndKey uRed = make_color_fp({1, 0, 0, 1},
false),
1590 uGreen = make_color_fp({0, 1, 0, 1},
false),
1591 sRed = make_color_fp({1, 0, 0, 1},
true),
1592 sGreen = make_color_fp({0, 1, 0, 1},
true);
1609 std::unique_ptr<skgpu::ganesh::SurfaceFillContext> testCtx =
1613 static constexpr std::array<float, 4>
kRed {1.0f, 0.0f, 0.0f, 1.0f};
1614 static constexpr std::array<float, 4>
kGreen{0.0f, 1.0f, 0.0f, 1.0f};
1615 static constexpr std::array<float, 4>
kBlue {0.0f, 0.0f, 1.0f, 1.0f};
1616 static constexpr std::array<float, 4>
kGray {0.499f, 0.499f, 0.499f, 1.0f};
1621 "uniform half color[4];"
1622 "half4 main(float2 xy) { return half4(color[0], color[1], color[2], color[3]); }"
1627 "color",
SkSpan(colorArray)));
1631 if (!testCtx->readPixels(directContext, pixmap, {0, 0})) {
1635 if (actual !=
GrColorPackRGBA(255 * colorArray[0], 255 * colorArray[1],
1636 255 * colorArray[2], 255 * colorArray[3])) {
1639 "Expected: [ %g %g %g %g ]\n"
1641 colorArray[0], colorArray[1],
1642 colorArray[2], colorArray[3],
static void test_invalid(skiatest::Reporter *r, const char path[])
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a)
static const uint64_t kGreen
static const uint64_t kBlue
static const uint64_t kRed
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
SkColorSpace * sk_srgb_singleton()
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
constexpr SkColor SK_ColorTRANSPARENT
constexpr SkColor SK_ColorGRAY
constexpr SkColor SK_ColorBLUE
constexpr SkColor SK_ColorRED
constexpr SkColor SK_ColorBLACK
constexpr SkColor SK_ColorGREEN
constexpr SkColor SK_ColorWHITE
SkRuntimeEffect * SkMakeRuntimeEffect(SkRuntimeEffect::Result(*make)(SkString, const SkRuntimeEffect::Options &), const char *sksl, SkRuntimeEffect::Options options=SkRuntimeEffect::Options{})
static void test_RuntimeEffect_Blenders(skiatest::Reporter *r, GrRecordingContext *grContext, const GraphiteInfo *graphite)
void test_invalid_effect(skiatest::Reporter *r, const char *src, const char *expected)
static bool read_pixels(SkSurface *surface, GrColor *pixels)
static void verify_2x2_surface_results(skiatest::Reporter *r, const SkRuntimeEffect *effect, SkSurface *surface, std::array< GrColor, 4 > expected)
std::function< void(SkCanvas *, SkPaint *)> PreTestFn
DEF_TEST(SkRuntimeEffectInvalid_NoInVariables, r)
static void test_RuntimeEffectObeysCapabilities(skiatest::Reporter *r, SkSurface *surface)
static sk_sp< SkShader > make_RGBW_shader()
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRuntimeEffectSimple_GPU, r, ctxInfo, CtsEnforcement::kApiLevel_T)
static sk_sp< SkSurface > make_surface(GrRecordingContext *grContext, const GraphiteInfo *graphite, SkISize size)
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(GrSkSLFP_Specialized, r, ctxInfo, CtsEnforcement::kApiLevel_T)
void paint_canvas(SkCanvas *canvas, SkPaint *paint, const PreTestFn &preTestCallback)
static void verify_draw_obeys_capabilities(skiatest::Reporter *r, const SkRuntimeEffect *effect, SkSurface *surface, const SkPaint &paint)
static void test_RuntimeEffectStructNameReuse(skiatest::Reporter *r, GrRecordingContext *rContext)
static void test_RuntimeEffect_Shaders(skiatest::Reporter *r, GrRecordingContext *grContext, const GraphiteInfo *graphite)
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static void dump(const float m[20], SkYUVColorSpace cs, bool rgb2yuv)
#define REPORTER_ASSERT(r, cond,...)
#define DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(name, reporter, graphite_context, ctsEnforcement)
#define REPORT_FAILURE(reporter, cond, message)
static SkScalar center(float pos0, float pos1)
GrDirectContextPriv priv()
static std::unique_ptr< GrFragmentProcessor > MakeColor(SkPMColor4f color)
std::unique_ptr< skgpu::ganesh::SurfaceFillContext > makeSFC(GrImageInfo, std::string_view label, SkBackingFit=SkBackingFit::kExact, int sampleCount=1, skgpu::Mipmapped=skgpu::Mipmapped::kNo, skgpu::Protected=skgpu::Protected::kNo, GrSurfaceOrigin=kTopLeft_GrSurfaceOrigin, skgpu::Budgeted=skgpu::Budgeted::kYes)
static GrSpecializedUniform< T > SpecializeIf(bool condition, const T &value)
static std::unique_ptr< GrSkSLFP > Make(const SkRuntimeEffect *effect, const char *name, std::unique_ptr< GrFragmentProcessor > inputFP, OptFlags optFlags, Args &&... args)
static sk_sp< SkBlender > Mode(SkBlendMode mode)
static sk_sp< SkBlender > Arithmetic(float k1, float k2, float k3, float k4, bool enforcePremul)
void drawPaint(const SkPaint &paint)
void clear(SkColor color)
void rotate(SkScalar degrees)
static sk_sp< const SkCapabilities > RasterBackend()
bool isAlphaUnchanged() const
SkColor4f filterColor4f(const SkColor4f &srcColor, SkColorSpace *srcCS, SkColorSpace *dstCS) const
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
const void * data() const
static sk_sp< SkData > MakeEmpty()
sk_sp< SkData > detachAsData()
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, SkScalar startAngle, SkScalar endAngle, uint32_t flags, const SkMatrix *localMatrix)
void setShader(sk_sp< SkShader > shader)
void setBlendMode(SkBlendMode mode)
sk_sp< SkBlender > makeBlender() const
BuilderUniform uniform(std::string_view name)
BuilderChild child(std::string_view name)
const SkRuntimeEffect * effect() const
static void AllowPrivateAccess(SkRuntimeEffect::Options *options)
static bool CanDraw(const SkCapabilities *, const SkSL::Program *)
static SkRuntimeEffect::Options ES3Options()
static Result MakeForColorFilter(SkString sksl, const Options &)
static Result MakeForBlender(SkString sksl, const Options &)
static Result MakeForShader(SkString sksl, const Options &)
static TracedShader MakeTraced(sk_sp< SkShader > shader, const SkIPoint &traceCoord)
sk_sp< SkColorFilter > makeColorFilter(sk_sp< const SkData > uniforms) const
const std::string & source() const
sk_sp< SkShader > makeShader(const SkMatrix *localMatrix=nullptr) const
constexpr size_t size() const
const char * c_str() const
T * init(Args &&... args)
void build(const char *src)
TestBlend(skiatest::Reporter *r, GrRecordingContext *grContext, const GraphiteInfo *graphite)
void test(GrColor expected, PreTestFn preTestCallback=nullptr)
SkRuntimeBlendBuilder::BuilderChild child(const char *name)
SkRuntimeBlendBuilder::BuilderUniform uniform(const char *name)
void test(std::array< GrColor, 4 > expected, PreTestFn preTestCallback=nullptr)
void test(std::array< GrColor, 4 > expected, PreTestFn preTestCallback=nullptr)
void build(const char *src)
SkRuntimeShaderBuilder::BuilderUniform uniform(const char *name)
SkRuntimeShaderBuilder::BuilderChild child(const char *name)
TestEffect(skiatest::Reporter *r, GrRecordingContext *grContext, const GraphiteInfo *graphite, SkISize size={2, 2})
void test(GrColor expected, PreTestFn preTestCallback=nullptr)
std::string trace(const SkIPoint &traceCoord)
FlutterSemanticsFlag flags
const uint8_t uint32_t uint32_t GError ** error
Dart_NativeFunction function
constexpr SkColor4f kWhite
constexpr SkColor4f kTransparent
constexpr SkColor4f kGray
PODArray< SkColor > colors
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
SK_API sk_sp< SkShader > Color(SkColor)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
constexpr bool starts_with(std::string_view str, std::string_view prefix)
constexpr bool ends_with(std::string_view str, std::string_view suffix)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
sk_sp< SkRuntimeEffect > effect