From 6fae0523629f9abf114d8b7413f71dc7295a13e0 Mon Sep 17 00:00:00 2001 From: John Stiles Date: Wed, 10 Nov 2021 14:06:52 -0500 Subject: [PATCH] Implement constant folding for index expressions into matrices. Indexing into a constant matrix is a constant expression, so we are obligated to support it for ES2 compatibility. Change-Id: Ibe1e5bac39d9a88ce0222997a38e8b6952fdb336 Bug: skia:12472 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/469819 Commit-Queue: John Stiles Auto-Submit: John Stiles Reviewed-by: Brian Osman --- resources/sksl/folding/ArraySizeFolding.sksl | 6 +++- src/sksl/ir/SkSLIndexExpression.cpp | 32 ++++++++++++++++++++ tests/sksl/folding/ArraySizeFolding.glsl | 3 +- tests/sksl/folding/MatrixFoldingES2.glsl | 19 ------------ 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/resources/sksl/folding/ArraySizeFolding.sksl b/resources/sksl/folding/ArraySizeFolding.sksl index 7bb8011aab..29c2b99a39 100644 --- a/resources/sksl/folding/ArraySizeFolding.sksl +++ b/resources/sksl/folding/ArraySizeFolding.sksl @@ -9,7 +9,11 @@ bool test() { int a[int4(1, 2, 3, 4).y]; int b[int(max(-5.5, 2.0))]; int c[two]; - return check_array_is_int_2(a) && check_array_is_int_2(b) && check_array_is_int_2(c); + int d[int2(float2x2(1, 2, 3, 4)[0]).y]; + return check_array_is_int_2(a) && + check_array_is_int_2(b) && + check_array_is_int_2(c) && + check_array_is_int_2(d); } bool check_array_is_float_3(float[3] x) { diff --git a/src/sksl/ir/SkSLIndexExpression.cpp b/src/sksl/ir/SkSLIndexExpression.cpp index bf2cc3ef47..64676a409b 100644 --- a/src/sksl/ir/SkSLIndexExpression.cpp +++ b/src/sksl/ir/SkSLIndexExpression.cpp @@ -9,6 +9,7 @@ #include "src/sksl/SkSLProgramSettings.h" #include "src/sksl/ir/SkSLBinaryExpression.h" #include "src/sksl/ir/SkSLConstructorArray.h" +#include "src/sksl/ir/SkSLConstructorCompound.h" #include "src/sksl/ir/SkSLIndexExpression.h" #include "src/sksl/ir/SkSLLiteral.h" #include "src/sksl/ir/SkSLSwizzle.h" @@ -115,6 +116,37 @@ std::unique_ptr IndexExpression::Make(const Context& context, return arguments[indexValue]->clone(); } } + + if (baseType.isMatrix()) { + // Matrices can be constructed with vectors that don't line up on column boundaries, + // so extracting out the values from the constructor can be tricky. Fortunately, we + // can reconstruct an equivalent vector using `getConstantSubexpression`. If we + // can't extract the data using `getConstantSubexpression`, it wasn't constant and + // we're not obligated to simplify anything. + const Expression* baseExpr = ConstantFolder::GetConstantValueForVariable(*base); + int vecWidth = baseType.rows(); + const Type& vecType = baseType.componentType().toCompound(context, + vecWidth, + /*rows=*/1); + indexValue *= vecWidth; + + ExpressionArray ctorArgs; + ctorArgs.reserve_back(vecWidth); + for (int slot = 0; slot < vecWidth; ++slot) { + if (const Expression* subexpr = baseExpr->getConstantSubexpression(indexValue + + slot)) { + ctorArgs.push_back(subexpr->clone()); + } else { + ctorArgs.reset(); + break; + } + } + + if (!ctorArgs.empty()) { + int line = ctorArgs.front()->fLine; + return ConstructorCompound::Make(context, line, vecType, std::move(ctorArgs)); + } + } } } diff --git a/tests/sksl/folding/ArraySizeFolding.glsl b/tests/sksl/folding/ArraySizeFolding.glsl index 04c7e60072..865c8be6cc 100644 --- a/tests/sksl/folding/ArraySizeFolding.glsl +++ b/tests/sksl/folding/ArraySizeFolding.glsl @@ -16,5 +16,6 @@ vec4 main() { float g[3]; int _2_b[2]; int _3_c[2]; - return (check_array_is_int_2_bi(_2_b) && check_array_is_int_2_bi(_3_c)) && test_param_bff(f, g) ? colorGreen : colorRed; + int _4_d[2]; + return ((check_array_is_int_2_bi(_2_b) && check_array_is_int_2_bi(_3_c)) && check_array_is_int_2_bi(_4_d)) && test_param_bff(f, g) ? colorGreen : colorRed; } diff --git a/tests/sksl/folding/MatrixFoldingES2.glsl b/tests/sksl/folding/MatrixFoldingES2.glsl index 2757ac39fc..d428cfe05d 100644 --- a/tests/sksl/folding/MatrixFoldingES2.glsl +++ b/tests/sksl/folding/MatrixFoldingES2.glsl @@ -9,24 +9,5 @@ vec4 main() { _0_ok = _0_ok && mat3(unknownInput) == mat3(mat2(1.0)); _0_ok = _0_ok && mat3(9.0, 0.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, unknownInput) == mat3(mat2(9.0)); _0_ok = _0_ok && vec4(testMatrix2x2) == vec4(1.0, 2.0, 3.0, 4.0); - _0_ok = _0_ok && mat2(5.0)[0] == vec2(5.0, 0.0); - _0_ok = _0_ok && mat2(5.0)[1] == vec2(0.0, 5.0); - _0_ok = _0_ok && mat2(5.0)[0].x == 5.0; - _0_ok = _0_ok && mat2(5.0)[0].y == 0.0; - _0_ok = _0_ok && mat2(5.0)[1].x == 0.0; - _0_ok = _0_ok && mat2(5.0)[1].y == 5.0; - const mat3 _1_m = mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); - _0_ok = _0_ok && _1_m[0] == vec3(1.0, 2.0, 3.0); - _0_ok = _0_ok && _1_m[1] == vec3(4.0, 5.0, 6.0); - _0_ok = _0_ok && _1_m[2] == vec3(7.0, 8.0, 9.0); - _0_ok = _0_ok && _1_m[0].x == 1.0; - _0_ok = _0_ok && _1_m[0].y == 2.0; - _0_ok = _0_ok && _1_m[0].z == 3.0; - _0_ok = _0_ok && _1_m[1].x == 4.0; - _0_ok = _0_ok && _1_m[1].y == 5.0; - _0_ok = _0_ok && _1_m[1].z == 6.0; - _0_ok = _0_ok && _1_m[2].x == 7.0; - _0_ok = _0_ok && _1_m[2].y == 8.0; - _0_ok = _0_ok && _1_m[2].z == 9.0; return _0_ok ? colorGreen : colorRed; }