SkSL interpreter now properly short-circuits boolean operators

Bug: skia:
Change-Id: If7acf4107498cabc049ad130814a3814383bd14b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243418
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2019-09-23 11:43:45 -04:00 committed by Skia Commit-Bot
parent 57ef680775
commit d166d2e62f
2 changed files with 62 additions and 9 deletions

View File

@ -627,6 +627,38 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
}
}
}
int count = std::max(SlotCount(lType), SlotCount(rType));
switch (op) {
case Token::Kind::LOGICALAND: {
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kDup);
this->write8(1);
this->write(ByteCodeInstruction::kMaskPush);
this->write(ByteCodeInstruction::kBranchIfAllFalse);
DeferredLocation falseLocation(this);
this->writeExpression(*b.fRight);
this->write(ByteCodeInstruction::kAndB);
falseLocation.set();
this->write(ByteCodeInstruction::kMaskPop);
return false;
}
case Token::Kind::LOGICALOR: {
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kDup);
this->write8(1);
this->write(ByteCodeInstruction::kNotB);
this->write(ByteCodeInstruction::kMaskPush);
this->write(ByteCodeInstruction::kBranchIfAllFalse);
DeferredLocation falseLocation(this);
this->writeExpression(*b.fRight);
this->write(ByteCodeInstruction::kOrB);
falseLocation.set();
this->write(ByteCodeInstruction::kMaskPop);
return false;
}
default:
break;
}
this->writeExpression(*b.fRight);
if (lVecOrMtx && !rVecOrMtx) {
for (int i = SlotCount(lType); i > 1; --i) {
@ -653,7 +685,6 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
this->write8(lRows);
this->write8(rCols);
} else {
int count = std::max(SlotCount(lType), SlotCount(rType));
switch (op) {
case Token::Kind::EQEQ:
this->writeTypedInstruction(lType, ByteCodeInstruction::kCompareIEQ,
@ -730,18 +761,10 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
count);
break;
case Token::Kind::LOGICALAND:
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kAndB);
break;
case Token::Kind::LOGICALNOT:
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kNotB);
break;
case Token::Kind::LOGICALOR:
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kOrB);
break;
case Token::Kind::LOGICALXOR:
SkASSERT(type_category(lType) == SkSL::TypeCategory::kBool && count == 1);
this->write(ByteCodeInstruction::kXorB);

View File

@ -209,6 +209,36 @@ DEF_TEST(SkSLInterpreterRemainder, r) {
0, 2, 4, 0, 0);
}
DEF_TEST(SkSLInterpreterAnd, r) {
test(r, "void main(inout half4 color) { if (color.r > color.g && color.g > color.b) "
"color = half4(color.a); }", 2, 1, 0, 3, 3, 3, 3, 3);
test(r, "void main(inout half4 color) { if (color.r > color.g && color.g > color.b) "
"color = half4(color.a); }", 1, 1, 0, 3, 1, 1, 0, 3);
test(r, "void main(inout half4 color) { if (color.r > color.g && color.g > color.b) "
"color = half4(color.a); }", 2, 1, 1, 3, 2, 1, 1, 3);
test(r, "int global; bool update() { global = 123; return true; }"
"void main(inout half4 color) { global = 0; if (color.r > color.g && update()) "
"color = half4(color.a); color.a = global; }", 2, 1, 1, 3, 3, 3, 3, 123);
test(r, "int global; bool update() { global = 123; return true; }"
"void main(inout half4 color) { global = 0; if (color.r > color.g && update()) "
"color = half4(color.a); color.a = global; }", 1, 1, 1, 3, 1, 1, 1, 0);
}
DEF_TEST(SkSLInterpreterOr, r) {
test(r, "void main(inout half4 color) { if (color.r > color.g || color.g > color.b) "
"color = half4(color.a); }", 2, 1, 0, 3, 3, 3, 3, 3);
test(r, "void main(inout half4 color) { if (color.r > color.g || color.g > color.b) "
"color = half4(color.a); }", 1, 1, 0, 3, 3, 3, 3, 3);
test(r, "void main(inout half4 color) { if (color.r > color.g || color.g > color.b) "
"color = half4(color.a); }", 1, 1, 1, 3, 1, 1, 1, 3);
test(r, "int global; bool update() { global = 123; return true; }"
"void main(inout half4 color) { global = 0; if (color.r > color.g || update()) "
"color = half4(color.a); color.a = global; }", 1, 1, 1, 3, 3, 3, 3, 123);
test(r, "int global; bool update() { global = 123; return true; }"
"void main(inout half4 color) { global = 0; if (color.r > color.g || update()) "
"color = half4(color.a); color.a = global; }", 2, 1, 1, 3, 3, 3, 3, 0);
}
DEF_TEST(SkSLInterpreterMatrix, r) {
float in[16];
float expected[16];