sksl can now fold constant vector or matrix equality expressions
Bug: skia:
Change-Id: Icaddae68e53ed3629bcdc04b5f0b541d9e4398e2
Reviewed-on: https://skia-review.googlesource.com/14260
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h
index 208031a..05f4096 100644
--- a/src/sksl/ir/SkSLConstructor.h
+++ b/src/sksl/ir/SkSLConstructor.h
@@ -81,6 +81,44 @@
return true;
}
+ bool compareConstant(const Context& context, const Expression& other) const override {
+ ASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
+ Constructor& c = (Constructor&) other;
+ if (c.fType.kind() == Type::kVector_Kind) {
+ for (int i = 0; i < fType.columns(); i++) {
+ if (!this->getVecComponent(i).compareConstant(context, c.getVecComponent(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
+ // a constant scalar constructor should have been collapsed down to the appropriate
+ // literal
+ ASSERT(fType.kind() == Type::kMatrix_Kind);
+ const FloatLiteral fzero(context, Position(), 0);
+ const IntLiteral izero(context, Position(), 0);
+ const Expression* zero;
+ if (fType.componentType() == *context.fFloat_Type) {
+ zero = &fzero;
+ } else {
+ ASSERT(fType.componentType() == *context.fInt_Type);
+ zero = &izero;
+ }
+ for (int col = 0; col < fType.columns(); col++) {
+ for (int row = 0; row < fType.rows(); row++) {
+ const Expression* component1 = getMatComponent(col, row);
+ const Expression* component2 = c.getMatComponent(col, row);
+ if (!(component1 ? component1 : zero)->compareConstant(
+ context,
+ component2 ? *component2 : *zero)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
const Expression& getVecComponent(int index) const {
ASSERT(fType.kind() == Type::kVector_Kind);
if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
@@ -118,6 +156,51 @@
return ((IntLiteral&) c).fValue;
}
+ // null return should be interpreted as zero
+ const Expression* getMatComponent(int col, int row) const {
+ ASSERT(this->isConstant());
+ ASSERT(fType.kind() == Type::kMatrix_Kind);
+ ASSERT(col < fType.columns() && row < fType.rows());
+ if (fArguments.size() == 1) {
+ if (fArguments[0]->fType.kind() == Type::kScalar_Kind) {
+ // single scalar argument, so matrix is of the form:
+ // x 0 0
+ // 0 x 0
+ // 0 0 x
+ // return x if col == row
+ return col == row ? fArguments[0].get() : nullptr;
+ }
+ if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) {
+ ASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind);
+ // single matrix argument. make sure we're within the argument's bounds.
+ const Type& argType = ((Constructor&) *fArguments[0]).fType;
+ if (col < argType.columns() && row < argType.rows()) {
+ // within bounds, defer to argument
+ return ((Constructor&) *fArguments[0]).getMatComponent(col, row);
+ }
+ // out of bounds, return 0
+ return nullptr;
+ }
+ }
+ int currentIndex = 0;
+ int targetIndex = col * fType.rows() + row;
+ for (const auto& arg : fArguments) {
+ ASSERT(targetIndex >= currentIndex);
+ ASSERT(arg->fType.rows() == 1);
+ if (currentIndex + arg->fType.columns() > targetIndex) {
+ if (arg->fType.columns() == 1) {
+ return arg.get();
+ } else {
+ ASSERT(arg->fType.kind() == Type::kVector_Kind);
+ ASSERT(arg->fKind == Expression::kConstructor_Kind);
+ return &((Constructor&) *arg).getVecComponent(targetIndex - currentIndex);
+ }
+ }
+ currentIndex += arg->fType.columns();
+ }
+ ABORT("can't happen, matrix component out of bounds");
+ }
+
std::vector<std::unique_ptr<Expression>> fArguments;
typedef Expression INHERITED;