Support structs in runtime effects
Uses the pipeline-stage callback mechanism. It mangles the type name
(with a test to verify that this works), and then calls defineStruct
with the entire SkSL struct definition string.
Bug: skia:10939
Change-Id: If14cf1b11faaa80ad8d4086cdacf68532bac43fc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368809
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/tests/SkRuntimeEffectTest.cpp b/tests/SkRuntimeEffectTest.cpp
index a36f03f..f364c53 100644
--- a/tests/SkRuntimeEffectTest.cpp
+++ b/tests/SkRuntimeEffectTest.cpp
@@ -401,3 +401,44 @@
REPORTER_ASSERT(r, c.fB == 0.5625f);
REPORTER_ASSERT(r, c.fA == 1.0f);
}
+
+static void test_RuntimeEffectStructNameReuse(skiatest::Reporter* r, GrRecordingContext* rContext) {
+ // Test that two different runtime effects can reuse struct names in a single paint operation
+ auto [childEffect, err] = SkRuntimeEffect::Make(SkString(
+ "uniform shader paint;"
+ "struct S { half4 rgba; };"
+ "void process(inout S s) { s.rgba.rgb *= 0.5; }"
+ "half4 main() { S s; s.rgba = sample(paint); process(s); return s.rgba; }"
+ ));
+ REPORTER_ASSERT(r, childEffect, "%s\n", err.c_str());
+ sk_sp<SkShader> nullChild = nullptr;
+ sk_sp<SkShader> child = childEffect->makeShader(/*uniforms=*/nullptr, &nullChild,
+ /*childCount=*/1, /*localMatrix=*/nullptr,
+ /*isOpaque=*/false);
+
+ SkImageInfo info = SkImageInfo::Make(2, 2, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ sk_sp<SkSurface> surface = rContext
+ ? SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info)
+ : SkSurface::MakeRaster(info);
+ REPORTER_ASSERT(r, surface);
+
+ TestEffect effect(r, surface);
+ effect.build(
+ "uniform shader child;"
+ "struct S { float2 coord; };"
+ "void process(inout S s) { s.coord = s.coord.yx; }"
+ "half4 main(float2 p) { S s; s.coord = p; process(s); return sample(child, s.coord); "
+ "}");
+ effect.child("child") = child;
+ effect.test(0xFF00407F, [](SkCanvas*, SkPaint* paint) {
+ paint->setColor4f({0.99608f, 0.50196f, 0.0f, 1.0f});
+ });
+}
+
+DEF_TEST(SkRuntimeStructNameReuse, r) {
+ test_RuntimeEffectStructNameReuse(r, nullptr);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRuntimeStructNameReuse_GPU, r, ctxInfo) {
+ test_RuntimeEffectStructNameReuse(r, ctxInfo.directContext());
+}
diff --git a/tests/SkSLTest.cpp b/tests/SkSLTest.cpp
index 214d52e..dcce46e 100644
--- a/tests/SkSLTest.cpp
+++ b/tests/SkSLTest.cpp
@@ -130,7 +130,7 @@
SKSL_TEST(SkSLIntFoldingES2, "folding/IntFoldingES2.sksl")
SKSL_TEST(SkSLFloatFolding, "folding/FloatFolding.sksl")
SKSL_TEST(SkSLMatrixFoldingES2, "folding/MatrixFoldingES2.sksl")
-SKSL_TEST_CPU(SkSLSelfAssignment, "folding/SelfAssignment.sksl")
+SKSL_TEST(SkSLSelfAssignment, "folding/SelfAssignment.sksl")
SKSL_TEST(SkSLShortCircuitBoolFolding, "folding/ShortCircuitBoolFolding.sksl")
SKSL_TEST(SkSLVectorScalarFolding, "folding/VectorScalarFolding.sksl")
SKSL_TEST(SkSLVectorVectorFolding, "folding/VectorVectorFolding.sksl")
@@ -173,6 +173,7 @@
SKSL_TEST(SkSLScalarConversionConstructorsES2, "shared/ScalarConversionConstructorsES2.sksl")
SKSL_TEST(SkSLStackingVectorCasts, "shared/StackingVectorCasts.sksl")
SKSL_TEST(SkSLStaticIf, "shared/StaticIf.sksl")
+SKSL_TEST(SkSLStructsInFunctions, "shared/StructsInFunctions.sksl")
SKSL_TEST(SkSLSwizzleBoolConstants, "shared/SwizzleBoolConstants.sksl")
SKSL_TEST(SkSLSwizzleByConstantIndex, "shared/SwizzleByConstantIndex.sksl")
SKSL_TEST(SkSLSwizzleConstants, "shared/SwizzleConstants.sksl")
@@ -192,12 +193,6 @@
*/
/*
-TODO(skia:10939): enable this test when Runtime Effects supports structs in function signatures
-SKSL_TEST(SkSLSelfAssignment, "folding/SelfAssignment.sksl")
-SKSL_TEST(SkSLStructsInFunctions, "shared/StructsInFunctions.sksl")
-*/
-
-/*
TODO(skia:11209): enable these tests when Runtime Effects have support for ES3
SKSL_TEST(SkSLIntFoldingES3, "folding/IntFoldingES3.sksl")
diff --git a/tests/sksl/inliner/TrivialArgumentsInlineDirectly.glsl b/tests/sksl/inliner/TrivialArgumentsInlineDirectly.glsl
index 96832b7..96479ba 100644
--- a/tests/sksl/inliner/TrivialArgumentsInlineDirectly.glsl
+++ b/tests/sksl/inliner/TrivialArgumentsInlineDirectly.glsl
@@ -5,8 +5,8 @@
uniform vec4 uh4;
uniform bool b;
struct S {
- vec4[1] ah4;
- float[1] ah;
+ vec4 ah4[1];
+ float ah[1];
vec4 h4;
float h;
};
diff --git a/tests/sksl/shared/Assignment.asm.frag b/tests/sksl/shared/Assignment.asm.frag
index f66558b..5c9be9d 100644
--- a/tests/sksl/shared/Assignment.asm.frag
+++ b/tests/sksl/shared/Assignment.asm.frag
@@ -15,6 +15,12 @@
OpName %ai4 "ai4"
OpName %ah2x4 "ah2x4"
OpName %af4 "af4"
+OpName %S "S"
+OpMemberName %S 0 "f"
+OpMemberName %S 1 "af"
+OpMemberName %S 2 "h4"
+OpMemberName %S 3 "ah4"
+OpName %s "s"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
@@ -34,10 +40,20 @@
OpDecorate %65 RelaxedPrecision
OpDecorate %62 RelaxedPrecision
OpDecorate %_arr_v4float_int_1 ArrayStride 16
-OpDecorate %87 RelaxedPrecision
-OpDecorate %94 RelaxedPrecision
-OpDecorate %95 RelaxedPrecision
-OpDecorate %98 RelaxedPrecision
+OpDecorate %_arr_float_int_5 ArrayStride 16
+OpDecorate %_arr_v4float_int_5 ArrayStride 16
+OpMemberDecorate %S 0 Offset 0
+OpMemberDecorate %S 1 Offset 16
+OpMemberDecorate %S 2 Offset 96
+OpMemberDecorate %S 2 RelaxedPrecision
+OpMemberDecorate %S 3 Offset 112
+OpMemberDecorate %S 3 RelaxedPrecision
+OpDecorate %88 RelaxedPrecision
+OpDecorate %92 RelaxedPrecision
+OpDecorate %108 RelaxedPrecision
+OpDecorate %115 RelaxedPrecision
+OpDecorate %116 RelaxedPrecision
+OpDecorate %122 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -87,6 +103,14 @@
%_arr_v4float_int_1 = OpTypeArray %v4float %int_1
%_ptr_Function__arr_v4float_int_1 = OpTypePointer Function %_arr_v4float_int_1
%73 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+%int_5 = OpConstant %int 5
+%_arr_float_int_5 = OpTypeArray %float %int_5
+%_arr_v4float_int_5 = OpTypeArray %v4float %int_5
+%S = OpTypeStruct %float %_arr_float_int_5 %v4float %_arr_v4float_int_5
+%_ptr_Function_S = OpTypePointer Function %S
+%85 = OpConstantComposite %v3float %float_9 %float_9 %float_9
+%89 = OpConstantComposite %v2float %float_5 %float_5
+%102 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
%_ptr_Function_v3float = OpTypePointer Function %v3float
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%_entrypoint = OpFunction %void None %15
@@ -103,6 +127,7 @@
%ai4 = OpVariable %_ptr_Function__arr_v4int_int_1 Function
%ah2x4 = OpVariable %_ptr_Function__arr_mat3v3float_int_1 Function
%af4 = OpVariable %_ptr_Function__arr_v4float_int_1 Function
+%s = OpVariable %_ptr_Function_S Function
OpStore %i4 %28
%32 = OpAccessChain %_ptr_Function_float %x %int_3
OpStore %32 %float_0
@@ -126,29 +151,53 @@
%75 = OpLoad %v4float %74
%76 = OpVectorShuffle %v4float %75 %73 6 4 7 5
OpStore %74 %76
-%77 = OpAccessChain %_ptr_Function_int %ai %int_0
-%78 = OpLoad %int %77
-%79 = OpAccessChain %_ptr_Function_v4int %ai4 %int_0
-%80 = OpLoad %v4int %79
-%81 = OpCompositeExtract %int %80 0
-%82 = OpIAdd %int %78 %81
-OpStore %77 %82
-%83 = OpAccessChain %_ptr_Function_v4float %af4 %int_0
-%84 = OpLoad %v4float %83
-%85 = OpAccessChain %_ptr_Function_v3float %ah2x4 %int_0 %int_0
-%87 = OpLoad %v3float %85
-%88 = OpCompositeExtract %float %87 0
-%89 = OpVectorTimesScalar %v4float %84 %88
-OpStore %83 %89
-%90 = OpAccessChain %_ptr_Function_int %i4 %int_1
-%91 = OpLoad %int %90
-%92 = OpIMul %int %91 %int_0
+%83 = OpAccessChain %_ptr_Function_float %s %int_0
+OpStore %83 %float_0
+%84 = OpAccessChain %_ptr_Function_float %s %int_1 %int_1
+OpStore %84 %float_0
+%86 = OpAccessChain %_ptr_Function_v4float %s %int_2
+%87 = OpLoad %v4float %86
+%88 = OpVectorShuffle %v4float %87 %85 5 6 4 3
+OpStore %86 %88
+%90 = OpAccessChain %_ptr_Function_v4float %s %int_3 %int_2
+%91 = OpLoad %v4float %90
+%92 = OpVectorShuffle %v4float %91 %89 0 4 2 5
OpStore %90 %92
-%93 = OpAccessChain %_ptr_Function_float %x %int_1
-%94 = OpLoad %float %93
-%95 = OpFMul %float %94 %float_0
-OpStore %93 %95
-%96 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
-%98 = OpLoad %v4float %96
-OpReturnValue %98
+%93 = OpAccessChain %_ptr_Function_int %ai %int_0
+%94 = OpLoad %int %93
+%95 = OpAccessChain %_ptr_Function_v4int %ai4 %int_0
+%96 = OpLoad %v4int %95
+%97 = OpCompositeExtract %int %96 0
+%98 = OpIAdd %int %94 %97
+OpStore %93 %98
+%99 = OpAccessChain %_ptr_Function_float %s %int_0
+OpStore %99 %float_1
+%100 = OpAccessChain %_ptr_Function_float %s %int_1 %int_0
+OpStore %100 %float_2
+%101 = OpAccessChain %_ptr_Function_v4float %s %int_2
+OpStore %101 %73
+%103 = OpAccessChain %_ptr_Function_v4float %s %int_3 %int_0
+OpStore %103 %102
+%104 = OpAccessChain %_ptr_Function_v4float %af4 %int_0
+%105 = OpLoad %v4float %104
+%106 = OpAccessChain %_ptr_Function_v3float %ah2x4 %int_0 %int_0
+%108 = OpLoad %v3float %106
+%109 = OpCompositeExtract %float %108 0
+%110 = OpVectorTimesScalar %v4float %105 %109
+OpStore %104 %110
+%111 = OpAccessChain %_ptr_Function_int %i4 %int_1
+%112 = OpLoad %int %111
+%113 = OpIMul %int %112 %int_0
+OpStore %111 %113
+%114 = OpAccessChain %_ptr_Function_float %x %int_1
+%115 = OpLoad %float %114
+%116 = OpFMul %float %115 %float_0
+OpStore %114 %116
+%117 = OpAccessChain %_ptr_Function_float %s %int_0
+%118 = OpLoad %float %117
+%119 = OpFMul %float %118 %float_0
+OpStore %117 %119
+%120 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%122 = OpLoad %v4float %120
+OpReturnValue %122
OpFunctionEnd
diff --git a/tests/sksl/shared/Assignment.glsl b/tests/sksl/shared/Assignment.glsl
index fe884e6..5f2fb97 100644
--- a/tests/sksl/shared/Assignment.glsl
+++ b/tests/sksl/shared/Assignment.glsl
@@ -1,6 +1,12 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
+struct S {
+ float f;
+ float af[5];
+ vec4 h4;
+ vec4 ah4[5];
+};
vec4 main() {
ivec4 i4;
i4 = ivec4(1, 2, 3, 4);
@@ -16,9 +22,19 @@
vec4 af4[1];
af4[0].x = 0.0;
af4[0].ywxz = vec4(1.0);
+ S s;
+ s.f = 0.0;
+ s.af[1] = 0.0;
+ s.h4.zxy = vec3(9.0);
+ s.ah4[2].yw = vec2(5.0);
ai[0] += ai4[0].x;
+ s.f = 1.0;
+ s.af[0] = 2.0;
+ s.h4 = vec4(1.0);
+ s.ah4[0] = vec4(2.0);
af4[0] *= ah2x4[0][0].x;
i4.y *= 0;
x.y *= 0.0;
+ s.f *= 0.0;
return colorGreen;
}
diff --git a/tests/sksl/shared/Assignment.metal b/tests/sksl/shared/Assignment.metal
index e28e820..7a8d59a 100644
--- a/tests/sksl/shared/Assignment.metal
+++ b/tests/sksl/shared/Assignment.metal
@@ -1,6 +1,12 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
+struct S {
+ float f;
+ array<float, 5> af;
+ float4 h4;
+ array<float4, 5> ah4;
+};
struct Uniforms {
float4 colorGreen;
};
@@ -27,10 +33,20 @@
array<float4, 1> af4;
af4[0].x = 0.0;
af4[0].ywxz = float4(1.0);
+ S s;
+ s.f = 0.0;
+ s.af[1] = 0.0;
+ s.h4.zxy = float3(9.0);
+ s.ah4[2].yw = float2(5.0);
ai[0] += ai4[0].x;
+ s.f = 1.0;
+ s.af[0] = 2.0;
+ s.h4 = float4(1.0);
+ s.ah4[0] = float4(2.0);
af4[0] *= ah2x4[0][0].x;
i4.y = i4.y * 0;
x.y = x.y * 0.0;
+ s.f *= 0.0;
_out.sk_FragColor = _uniforms.colorGreen;
return _out;
}
diff --git a/tests/sksl/shared/StructMaxDepth.glsl b/tests/sksl/shared/StructMaxDepth.glsl
index 0b3f753..d6ab111 100644
--- a/tests/sksl/shared/StructMaxDepth.glsl
+++ b/tests/sksl/shared/StructMaxDepth.glsl
@@ -25,27 +25,27 @@
};
in S8 s8;
struct SA1 {
- int[8] x;
+ int x[8];
};
struct SA2 {
- SA1[7] x;
+ SA1 x[7];
};
struct SA3 {
- SA2[6] x;
+ SA2 x[6];
};
struct SA4 {
- SA3[5] x;
+ SA3 x[5];
};
struct SA5 {
- SA4[4] x;
+ SA4 x[4];
};
struct SA6 {
- SA5[3] x;
+ SA5 x[3];
};
struct SA7 {
- SA6[2] x;
+ SA6 x[2];
};
struct SA8 {
- SA7[1] x;
+ SA7 x[1];
};
in SA8 sa8[9];
diff --git a/tests/sksl/shared/Structs.glsl b/tests/sksl/shared/Structs.glsl
index 71b7630..07d907c 100644
--- a/tests/sksl/shared/Structs.glsl
+++ b/tests/sksl/shared/Structs.glsl
@@ -7,7 +7,7 @@
A a1;
struct B {
float x;
- float[2] y;
+ float y[2];
layout (binding = 1) A z;
};
B b1;