diff --git a/resources/sksl/folding/ArrayFolding.sksl b/resources/sksl/folding/ArrayFolding.sksl index c12aec3e96..b253a5bc74 100644 --- a/resources/sksl/folding/ArrayFolding.sksl +++ b/resources/sksl/folding/ArrayFolding.sksl @@ -17,15 +17,15 @@ bool test() { const int b [x[x[z]]] = int[2](1, 2); const int c [x[x[x[z]]]] = int[3](1, 2, 3); - // The unreferenced array elements are safe to eliminate. - int flatten0 = (int[3](side_effecting(1), 2, 3))[0]; - int flatten1 = (int[3](1, side_effecting(2), 3))[1]; - int flatten2 = (int[3](1, 2, side_effecting(3)))[2]; + // Constant-expression arrays can be optimized. + int flatten0 = (int[3](1, 2, 3))[0]; + int flatten1 = (int[3](1, 2, 3))[1]; + int flatten2 = (int[3](1, 2, 3))[2]; - // Some unreferenced array elements have a side effect and are not safe to eliminate. + // Non-constant-expression arrays are not eligible for optimization. int noFlatten0 = (int[3](1, side_effecting(2), 3))[0]; int noFlatten1 = (int[3](side_effecting(1), 2, 3))[1]; - int noFlatten2 = (int[3](side_effecting(1), side_effecting(2), 3))[2]; + int noFlatten2 = (int[3](1, 2, side_effecting(3)))[2]; return (x == xx) && !(x != xx) && (x != y) && !(x == y) && (x[0] == y[0]) && (c == x) && diff --git a/src/sksl/ir/SkSLIndexExpression.cpp b/src/sksl/ir/SkSLIndexExpression.cpp index bd48525b17..bf2cc3ef47 100644 --- a/src/sksl/ir/SkSLIndexExpression.cpp +++ b/src/sksl/ir/SkSLIndexExpression.cpp @@ -7,6 +7,8 @@ #include "src/sksl/SkSLConstantFolder.h" #include "src/sksl/SkSLProgramSettings.h" +#include "src/sksl/ir/SkSLBinaryExpression.h" +#include "src/sksl/ir/SkSLConstructorArray.h" #include "src/sksl/ir/SkSLIndexExpression.h" #include "src/sksl/ir/SkSLLiteral.h" #include "src/sksl/ir/SkSLSwizzle.h" @@ -100,11 +102,22 @@ std::unique_ptr IndexExpression::Make(const Context& context, // Swizzling is harmless and can unlock further simplifications for some base types. return Swizzle::Make(context, std::move(base), ComponentArray{(int8_t)indexValue}); } + + if (baseType.isArray()) { + // Indexing an constant array constructor with a constant index can just pluck out + // the requested value from the array. + const Expression* baseExpr = ConstantFolder::GetConstantValueForVariable(*base); + if (baseExpr->is() && baseExpr->isCompileTimeConstant()) { + const ConstructorArray& arrayCtor = baseExpr->as(); + const ExpressionArray& arguments = arrayCtor.arguments(); + SkASSERT(arguments.count() == baseType.columns()); + + return arguments[indexValue]->clone(); + } + } } } - // TODO(skia:12472): constantArray[constantExpr] should be compile-time evaluated. - return std::make_unique(context, std::move(base), std::move(index)); } diff --git a/tests/sksl/folding/ArrayFolding.glsl b/tests/sksl/folding/ArrayFolding.glsl index b18096587c..1dfa5f3d73 100644 --- a/tests/sksl/folding/ArrayFolding.glsl +++ b/tests/sksl/folding/ArrayFolding.glsl @@ -1,9 +1,18 @@ -### Compilation failed: -error: 16: array size must be an integer -error: 17: array size must be an integer -error: 17: expected 'int[1]', but found 'int[2]' -error: 18: array size must be an integer -error: 18: expected 'int[1]', but found 'int[3]' -error: 31: unknown identifier 'c' -6 errors +out vec4 sk_FragColor; +uniform vec4 colorRed; +uniform vec4 colorGreen; +int globalValue = 0; +int side_effecting_ii(int value) { + globalValue++; + return value; +} +vec4 main() { + int _7_flatten0 = 1; + int _8_flatten1 = 2; + int _9_flatten2 = 3; + int _10_noFlatten0 = int[3](1, side_effecting_ii(2), 3)[0]; + int _11_noFlatten1 = int[3](side_effecting_ii(1), 2, 3)[1]; + int _12_noFlatten2 = int[3](1, 2, side_effecting_ii(3))[2]; + return (_7_flatten0 == _10_noFlatten0 && _8_flatten1 == _11_noFlatten1) && _9_flatten2 == _12_noFlatten2 ? colorGreen : colorRed; +} diff --git a/tests/sksl/shared/ConstArray.asm.frag b/tests/sksl/shared/ConstArray.asm.frag index d5257efe9f..52204f0063 100644 --- a/tests/sksl/shared/ConstArray.asm.frag +++ b/tests/sksl/shared/ConstArray.asm.frag @@ -5,21 +5,13 @@ OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise OpExecutionMode %_entrypoint_v OriginUpperLeft OpName %sk_FragColor "sk_FragColor" OpName %sk_Clockwise "sk_Clockwise" -OpName %test "test" OpName %_entrypoint_v "_entrypoint_v" OpName %main "main" OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing -OpDecorate %test RelaxedPrecision -OpDecorate %_arr_float_int_4 ArrayStride 16 -OpDecorate %17 RelaxedPrecision -OpDecorate %33 RelaxedPrecision -OpDecorate %36 RelaxedPrecision -OpDecorate %39 RelaxedPrecision -OpDecorate %42 RelaxedPrecision -OpDecorate %43 RelaxedPrecision +OpDecorate %24 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -27,45 +19,25 @@ OpDecorate %43 RelaxedPrecision %bool = OpTypeBool %_ptr_Input_bool = OpTypePointer Input %bool %sk_Clockwise = OpVariable %_ptr_Input_bool Input -%int = OpTypeInt 32 1 -%int_4 = OpConstant %int 4 -%_arr_float_int_4 = OpTypeArray %float %int_4 -%_ptr_Private__arr_float_int_4 = OpTypePointer Private %_arr_float_int_4 -%test = OpVariable %_ptr_Private__arr_float_int_4 Private -%float_0 = OpConstant %float 0 -%float_1 = OpConstant %float 1 %void = OpTypeVoid -%20 = OpTypeFunction %void +%12 = OpTypeFunction %void %v2float = OpTypeVector %float 2 -%23 = OpConstantComposite %v2float %float_0 %float_0 +%float_0 = OpConstant %float 0 +%16 = OpConstantComposite %v2float %float_0 %float_0 %_ptr_Function_v2float = OpTypePointer Function %v2float -%27 = OpTypeFunction %v4float %_ptr_Function_v2float -%int_0 = OpConstant %int 0 -%_ptr_Private_float = OpTypePointer Private %float -%int_1 = OpConstant %int 1 -%int_2 = OpConstant %int 2 -%int_3 = OpConstant %int 3 -%_entrypoint_v = OpFunction %void None %20 -%21 = OpLabel -%24 = OpVariable %_ptr_Function_v2float Function -OpStore %24 %23 -%26 = OpFunctionCall %v4float %main %24 -OpStore %sk_FragColor %26 +%20 = OpTypeFunction %v4float %_ptr_Function_v2float +%float_1 = OpConstant %float 1 +%24 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1 +%_entrypoint_v = OpFunction %void None %12 +%13 = OpLabel +%17 = OpVariable %_ptr_Function_v2float Function +OpStore %17 %16 +%19 = OpFunctionCall %v4float %main %17 +OpStore %sk_FragColor %19 OpReturn OpFunctionEnd -%main = OpFunction %v4float None %27 -%28 = OpFunctionParameter %_ptr_Function_v2float -%29 = OpLabel -%17 = OpCompositeConstruct %_arr_float_int_4 %float_0 %float_1 %float_0 %float_1 -OpStore %test %17 -%31 = OpAccessChain %_ptr_Private_float %test %int_0 -%33 = OpLoad %float %31 -%35 = OpAccessChain %_ptr_Private_float %test %int_1 -%36 = OpLoad %float %35 -%38 = OpAccessChain %_ptr_Private_float %test %int_2 -%39 = OpLoad %float %38 -%41 = OpAccessChain %_ptr_Private_float %test %int_3 -%42 = OpLoad %float %41 -%43 = OpCompositeConstruct %v4float %33 %36 %39 %42 -OpReturnValue %43 +%main = OpFunction %v4float None %20 +%21 = OpFunctionParameter %_ptr_Function_v2float +%22 = OpLabel +OpReturnValue %24 OpFunctionEnd diff --git a/tests/sksl/shared/ConstArray.glsl b/tests/sksl/shared/ConstArray.glsl index 8455e108bd..e26d14f25a 100644 --- a/tests/sksl/shared/ConstArray.glsl +++ b/tests/sksl/shared/ConstArray.glsl @@ -1,6 +1,5 @@ out vec4 sk_FragColor; -const float test[4] = float[4](0.0, 1.0, 0.0, 1.0); vec4 main() { - return vec4(test[0], test[1], test[2], test[3]); + return vec4(0.0, 1.0, 0.0, 1.0); } diff --git a/tests/sksl/shared/ConstArray.metal b/tests/sksl/shared/ConstArray.metal index f1237ff0e4..e97e542558 100644 --- a/tests/sksl/shared/ConstArray.metal +++ b/tests/sksl/shared/ConstArray.metal @@ -6,14 +6,9 @@ struct Inputs { struct Outputs { half4 sk_FragColor [[color(0)]]; }; -struct Globals { - const array test; -}; fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Globals _globals{array{0.0h, 1.0h, 0.0h, 1.0h}}; - (void)_globals; Outputs _out; (void)_out; - _out.sk_FragColor = half4(_globals.test[0], _globals.test[1], _globals.test[2], _globals.test[3]); + _out.sk_FragColor = half4(0.0h, 1.0h, 0.0h, 1.0h); return _out; }