Interpreter: Matrix/Vector multiplication

Change-Id: I3dc5e5be1cf12c581cce3854d0db7e73db6e1fd9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/216681
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLInterpreter.cpp b/src/sksl/SkSLInterpreter.cpp
index a0553f7..4e81a33 100644
--- a/src/sksl/SkSLInterpreter.cpp
+++ b/src/sksl/SkSLInterpreter.cpp
@@ -179,6 +179,13 @@
             printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
             break;
         }
+        case ByteCodeInstruction::kMatrixMultiply: {
+            int lCols = READ8();
+            int lRows = READ8();
+            int rCols = READ8();
+            printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
+            break;
+        }
         VECTOR_DISASSEMBLE(kMix, "mix")
         VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
         VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
@@ -571,6 +578,27 @@
                 break;
             }
 
+            case ByteCodeInstruction::kMatrixMultiply: {
+                int lCols = READ8();
+                int lRows = READ8();
+                int rCols = READ8();
+                int rRows = lCols;
+                float tmp[16] = { 0.0f };
+                float* B = &(sp - (rCols * rRows) + 1)->fFloat;
+                float* A = B - (lCols * lRows);
+                for (int c = 0; c < rCols; ++c) {
+                    for (int r = 0; r < lRows; ++r) {
+                        for (int j = 0; j < lCols; ++j) {
+                            tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
+                        }
+                    }
+                }
+                sp -= (lCols * lRows) + (rCols * rRows);
+                memcpy(sp + 1, tmp, rCols * lRows * sizeof(Value));
+                sp += (rCols * lRows);
+                break;
+            }
+
             // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
             case ByteCodeInstruction::kMix4:
                 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);