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:
parent
57ef680775
commit
d166d2e62f
@ -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);
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user