Allow compile-time intrinsic evaluation to read const variables.

Previously, the code neglected to resolve constant variables into
values. This meant that expressions like `lessThan(zero, one)` could not
be compile-time evaluated even when `zero` and `one` have known values.

Change-Id: I2f5ce303e3dcc682be14e4d2485e24dd7c59212e
Bug: skia:10835
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/405536
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
John Stiles 2021-05-06 23:55:19 -04:00 committed by Skia Commit-Bot
parent aaac4e4e3e
commit 1dc2d0fe0f
9 changed files with 38 additions and 27 deletions

View File

@ -11,10 +11,13 @@ bool test() {
bool h = false == true;
bool i = true == !false;
bool j = false == !false;
bool k = all(bool3(1 == 1, !false, 123 > 12)); // all are true
bool l = all(bool4(true, 1 == 2, true, true)); // three out of four are true
bool m = any(bool4(true, 1 == 2, true, true)); // three out of four are true
bool n = any(bool2(0 == 1, false)); // none are true
const bool TRUE = true;
const bool FALSE = false;
bool k = all(bool4(1 == 1, !false, 123 > 12, TRUE)); // all are true
bool l = all(bool3(TRUE, 1 == 2, true)); // three out of four are true
bool m = any(bool4(true, 1 == 2, true, TRUE)); // three out of four are true
bool n = any(bool2(0 == 1, FALSE)); // none are true
return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n;
}

View File

@ -2,8 +2,9 @@ uniform half4 a, b;
uniform uint2 c, d;
uniform int3 e, f;
void main() {
const int4 int4_zero = int4(0);
bool4 expectTTFF = equal(half4(3, 3, 3.25, 100), half4(3));
bool4 expectFFTT = equal(int4(0), int4(-100, -50, 0, 0));
bool4 expectFFTT = equal(int4_zero, int4(-100, -50, 0, 0));
sk_FragColor.x = equal(a, b).x ? 1 : 0;
sk_FragColor.y = equal(c, d).y ? 1 : 0;

View File

@ -2,8 +2,9 @@ uniform half4 a, b;
uniform uint2 c, d;
uniform int3 e, f;
void main() {
const int4 int4_zero = int4(0);
bool4 expectFFTT = greaterThan(half4(1, 2, 2.5, 2.75), half4(2.25));
bool4 expectTTFF = greaterThan(int4(0), int4(-100, -50, 0, 50));
bool4 expectTTFF = greaterThan(int4_zero, int4(-100, -50, 0, 50));
sk_FragColor.x = greaterThan(a, b).x ? 1 : 0;
sk_FragColor.y = greaterThan(c, d).y ? 1 : 0;

View File

@ -2,8 +2,9 @@ uniform half4 a, b;
uniform uint2 c, d;
uniform int3 e, f;
void main() {
const int4 int4_zero = int4(0);
bool4 expectFFTT = greaterThanEqual(half4(1, 2, 2.25, 2.5), half4(2.25));
bool4 expectTTFF = greaterThanEqual(int4(0), int4(-50, 0, 50, 100));
bool4 expectTTFF = greaterThanEqual(int4_zero, int4(-50, 0, 50, 100));
sk_FragColor.x = greaterThanEqual(a, b).x ? 1 : 0;
sk_FragColor.y = greaterThanEqual(c, d).y ? 1 : 0;

View File

@ -2,8 +2,9 @@ uniform half4 a, b;
uniform uint2 c, d;
uniform int3 e, f;
void main() {
const int4 int4_zero = int4(0);
bool4 expectTTFF = lessThan(half4(1, 2, 2.5, 2.75), half4(2.25));
bool4 expectFFTT = lessThan(int4(0), int4(-50, 0, 50, 100));
bool4 expectFFTT = lessThan(int4_zero, int4(-50, 0, 50, 100));
sk_FragColor.x = lessThan(a, b).x ? 1 : 0;
sk_FragColor.y = lessThan(c, d).y ? 1 : 0;

View File

@ -2,8 +2,9 @@ uniform half4 a, b;
uniform uint2 c, d;
uniform int3 e, f;
void main() {
const int4 int4_zero = int4(0);
bool4 expectTTFF = lessThanEqual(half4(2, 2.25, 2.5, 2.75), half4(2.25));
bool4 expectFFTT = lessThanEqual(int4(0), int4(-100, -50, 0, 50));
bool4 expectFFTT = lessThanEqual(int4_zero, int4(-100, -50, 0, 50));
sk_FragColor.x = lessThanEqual(a, b).x ? 1 : 0;
sk_FragColor.y = lessThanEqual(c, d).y ? 1 : 0;

View File

@ -2,8 +2,9 @@ uniform half4 a, b;
uniform uint2 c, d;
uniform int3 e, f;
void main() {
const int4 int4_zero = int4(0);
bool4 expectFFTT = notEqual(half4(3, 3, 3.25, 100), half4(3));
bool4 expectTTFF = notEqual(int4(0), int4(-100, -50, 0, 0));
bool4 expectTTFF = notEqual(int4_zero, int4(-100, -50, 0, 0));
sk_FragColor.x = notEqual(a, b).x ? 1 : 0;
sk_FragColor.y = notEqual(c, d).y ? 1 : 0;

View File

@ -6,6 +6,7 @@
*/
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
@ -18,7 +19,8 @@ namespace SkSL {
static bool has_compile_time_constant_arguments(const ExpressionArray& arguments) {
for (const std::unique_ptr<Expression>& arg : arguments) {
if (!arg->isCompileTimeConstant()) {
const Expression* expr = ConstantFolder::GetConstantValueForVariable(*arg);
if (!expr->isCompileTimeConstant()) {
return false;
}
}
@ -30,19 +32,19 @@ static std::unique_ptr<Expression> coalesce_bool_vector(
bool startingState,
const std::function<bool(bool, bool)>& coalesce) {
SkASSERT(arguments.size() == 1);
const Expression& arg = *arguments.front();
const Type& type = arg.type();
const Expression* arg = ConstantFolder::GetConstantValueForVariable(*arguments.front());
const Type& type = arg->type();
SkASSERT(type.isVector());
SkASSERT(type.componentType().isBoolean());
bool value = startingState;
for (int index = 0; index < type.columns(); ++index) {
const Expression* subexpression = arg.getConstantSubexpression(index);
const Expression* subexpression = arg->getConstantSubexpression(index);
SkASSERT(subexpression);
value = coalesce(value, subexpression->as<BoolLiteral>().value());
}
return BoolLiteral::Make(arg.fOffset, value, &type.componentType());
return BoolLiteral::Make(arg->fOffset, value, &type.componentType());
}
template <typename LITERAL, typename FN>
@ -77,16 +79,16 @@ static std::unique_ptr<Expression> optimize_comparison(const Context& context,
const ExpressionArray& arguments,
const FN& compare) {
SkASSERT(arguments.size() == 2);
const Expression& left = *arguments[0];
const Expression& right = *arguments[1];
const Expression* left = ConstantFolder::GetConstantValueForVariable(*arguments[0]);
const Expression* right = ConstantFolder::GetConstantValueForVariable(*arguments[1]);
if (left.type().componentType().isFloat()) {
return optimize_comparison_of_type<FloatLiteral>(context, left, right, compare);
if (left->type().componentType().isFloat()) {
return optimize_comparison_of_type<FloatLiteral>(context, *left, *right, compare);
}
if (left.type().componentType().isInteger()) {
return optimize_comparison_of_type<IntLiteral>(context, left, right, compare);
if (left->type().componentType().isInteger()) {
return optimize_comparison_of_type<IntLiteral>(context, *left, *right, compare);
}
SkDEBUGFAILF("unsupported type %s", left.type().description().c_str());
SkDEBUGFAILF("unsupported type %s", left->type().description().c_str());
return nullptr;
}

View File

@ -13,9 +13,9 @@ vec4 main() {
bool _7_h = false;
bool _8_i = true;
bool _9_j = false;
bool _10_k = true;
bool _11_l = false;
bool _12_m = true;
bool _13_n = false;
return ((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _10_k) && !_11_l) && _12_m) && !_13_n ? colorGreen : colorRed;
bool _12_k = true;
bool _13_l = false;
bool _14_m = true;
bool _15_n = false;
return ((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n ? colorGreen : colorRed;
}