Add support for 2x2 matrices

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1755483002

Review URL: https://codereview.chromium.org/1755483002
diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h
index 834c185..a045153 100644
--- a/include/gpu/GrTypesPriv.h
+++ b/include/gpu/GrTypesPriv.h
@@ -21,6 +21,7 @@
     kVec2f_GrSLType,
     kVec3f_GrSLType,
     kVec4f_GrSLType,
+    kMat22f_GrSLType,
     kMat33f_GrSLType,
     kMat44f_GrSLType,
     kSampler2D_GrSLType,
@@ -75,7 +76,7 @@
  */
 static inline int GrSLTypeVectorCount(GrSLType type) {
     SkASSERT(type >= 0 && type < static_cast<GrSLType>(kGrSLTypeCount));
-    static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1, -1, -1, 1, 1, 1 };
+    static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1, -1, -1, -1, 1, 1, 1 };
     return kCounts[type];
 
     GR_STATIC_ASSERT(0 == kVoid_GrSLType);
@@ -83,14 +84,15 @@
     GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
     GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
     GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
-    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
-    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
-    GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
-    GR_STATIC_ASSERT(10 == kBool_GrSLType);
-    GR_STATIC_ASSERT(11 == kInt_GrSLType);
-    GR_STATIC_ASSERT(12 == kUint_GrSLType);
+    GR_STATIC_ASSERT(5 == kMat22f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(7 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(10 == kSampler2DRect_GrSLType);
+    GR_STATIC_ASSERT(11 == kBool_GrSLType);
+    GR_STATIC_ASSERT(12 == kInt_GrSLType);
+    GR_STATIC_ASSERT(13 == kUint_GrSLType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kCounts) == kGrSLTypeCount);
 }
 
@@ -109,22 +111,23 @@
 /** Is the shading language type float (including vectors/matrices)? */
 static inline bool GrSLTypeIsFloatType(GrSLType type) {
     SkASSERT(type >= 0 && type < static_cast<GrSLType>(kGrSLTypeCount));
-    return (type >= 1 && type <= 6);
+    return type >= kFloat_GrSLType && type <= kMat44f_GrSLType;
 
     GR_STATIC_ASSERT(0 == kVoid_GrSLType);
     GR_STATIC_ASSERT(1 == kFloat_GrSLType);
     GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
     GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
     GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
-    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
-    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
-    GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
-    GR_STATIC_ASSERT(10 == kBool_GrSLType);
-    GR_STATIC_ASSERT(11 == kInt_GrSLType);
-    GR_STATIC_ASSERT(12 == kUint_GrSLType);
-    GR_STATIC_ASSERT(13 == kGrSLTypeCount);
+    GR_STATIC_ASSERT(5 == kMat22f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(7 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(10 == kSampler2DRect_GrSLType);
+    GR_STATIC_ASSERT(11 == kBool_GrSLType);
+    GR_STATIC_ASSERT(12 == kInt_GrSLType);
+    GR_STATIC_ASSERT(13 == kUint_GrSLType);
+    GR_STATIC_ASSERT(14 == kGrSLTypeCount);
 }
 
 /** Is the shading language type integral (including vectors/matrices)? */
@@ -137,15 +140,16 @@
     GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
     GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
     GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
-    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
-    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
-    GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
-    GR_STATIC_ASSERT(10 == kBool_GrSLType);
-    GR_STATIC_ASSERT(11 == kInt_GrSLType);
-    GR_STATIC_ASSERT(12 == kUint_GrSLType);
-    GR_STATIC_ASSERT(13 == kGrSLTypeCount);
+    GR_STATIC_ASSERT(5 == kMat22f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(7 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(10 == kSampler2DRect_GrSLType);
+    GR_STATIC_ASSERT(11 == kBool_GrSLType);
+    GR_STATIC_ASSERT(12 == kInt_GrSLType);
+    GR_STATIC_ASSERT(13 == kUint_GrSLType);
+    GR_STATIC_ASSERT(14 == kGrSLTypeCount);
 }
 
 /** Is the shading language type numeric (including vectors/matrices)? */
@@ -162,8 +166,9 @@
         2 * sizeof(float),        // kVec2f_GrSLType
         3 * sizeof(float),        // kVec3f_GrSLType
         4 * sizeof(float),        // kVec4f_GrSLType
-        9 * sizeof(float),        // kMat33f_GrSLType
-        16 * sizeof(float),       // kMat44f_GrSLType
+        2 * 2 * sizeof(float),    // kMat22f_GrSLType
+        3 * 3 * sizeof(float),    // kMat33f_GrSLType
+        4 * 4 * sizeof(float),    // kMat44f_GrSLType
         0,                        // kSampler2D_GrSLType
         0,                        // kSamplerExternal_GrSLType
         0,                        // kSampler2DRect_GrSLType
@@ -178,24 +183,25 @@
     GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
     GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
     GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
-    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
-    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
-    GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
-    GR_STATIC_ASSERT(10 == kBool_GrSLType);
-    GR_STATIC_ASSERT(11 == kInt_GrSLType);
-    GR_STATIC_ASSERT(12 == kUint_GrSLType);
-    GR_STATIC_ASSERT(13 == kGrSLTypeCount);
+    GR_STATIC_ASSERT(5 == kMat22f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(7 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(10 == kSampler2DRect_GrSLType);
+    GR_STATIC_ASSERT(11 == kBool_GrSLType);
+    GR_STATIC_ASSERT(12 == kInt_GrSLType);
+    GR_STATIC_ASSERT(13 == kUint_GrSLType);
+    GR_STATIC_ASSERT(14 == kGrSLTypeCount);
 }
 
 static inline bool GrSLTypeIsSamplerType(GrSLType type) {
     SkASSERT(type >= 0 && type < static_cast<GrSLType>(kGrSLTypeCount));
-    return type >= 7 && type <= 9;
+    return type >= kSampler2D_GrSLType && type <= kSampler2DRect_GrSLType;
 
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
-    GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(10 == kSampler2DRect_GrSLType);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index a75ecde..d5b48f7 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -11,8 +11,8 @@
 #include "glsl/GrGLSLUniformHandler.h"
 
 #define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \
-         SkASSERT(arrayCount <= uni.fArrayCount || \
-                  (1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount))
+         SkASSERT((COUNT) <= (UNI).fArrayCount || \
+                  (1 == (COUNT) && GrGLSLShaderVar::kNonArray == (UNI).fArrayCount))
 
 GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, GrGLuint programID,
                                                const UniformInfoArray& uniforms,
@@ -201,67 +201,65 @@
     }
 }
 
+void GrGLProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
+    this->setMatrices<2>(u, 1, matrix);
+}
+
 void GrGLProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
-    const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat33f_GrSLType);
-    SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
-    SkDEBUGCODE(this->printUnused(uni);)
-    if (kUnusedUniform != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fFSLocation, 1, false, matrix));
-    }
-    if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fVSLocation, 1, false, matrix));
-    }
+    this->setMatrices<3>(u, 1, matrix);
 }
 
 void GrGLProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
-    const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat44f_GrSLType);
-    SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
-    SkDEBUGCODE(this->printUnused(uni);)
-    if (kUnusedUniform != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fFSLocation, 1, false, matrix));
-    }
-    if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fVSLocation, 1, false, matrix));
-    }
+    this->setMatrices<4>(u, 1, matrix);
 }
 
-void GrGLProgramDataManager::setMatrix3fv(UniformHandle u,
-                                          int arrayCount,
-                                          const float matrices[]) const {
+void GrGLProgramDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
+    this->setMatrices<2>(u, arrayCount, m);
+}
+
+void GrGLProgramDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
+    this->setMatrices<3>(u, arrayCount, m);
+}
+
+void GrGLProgramDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
+    this->setMatrices<4>(u, arrayCount, m);
+}
+
+template<int N> struct set_uniform_matrix;
+
+template<int N> inline void GrGLProgramDataManager::setMatrices(UniformHandle u,
+                                                                int arrayCount,
+                                                                const float matrices[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat33f_GrSLType);
+    SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2));
     SkASSERT(arrayCount > 0);
     ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
     SkDEBUGCODE(this->printUnused(uni);)
     if (kUnusedUniform != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(),
-                   UniformMatrix3fv(uni.fFSLocation, arrayCount, false, matrices));
+        set_uniform_matrix<N>::set(fGpu->glInterface(), uni.fFSLocation, arrayCount, matrices);
     }
     if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(),
-                   UniformMatrix3fv(uni.fVSLocation, arrayCount, false, matrices));
+        set_uniform_matrix<N>::set(fGpu->glInterface(), uni.fVSLocation, arrayCount, matrices);
     }
 }
 
-void GrGLProgramDataManager::setMatrix4fv(UniformHandle u,
-                                          int arrayCount,
-                                          const float matrices[]) const {
-    const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat44f_GrSLType);
-    SkASSERT(arrayCount > 0);
-    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
-    SkDEBUGCODE(this->printUnused(uni);)
-    if (kUnusedUniform != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(),
-                   UniformMatrix4fv(uni.fFSLocation, arrayCount, false, matrices));
+template<> struct set_uniform_matrix<2> {
+    inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
+        GR_GL_CALL(gli, UniformMatrix2fv(loc, cnt, false, m));
     }
-    if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) {
-        GR_GL_CALL(fGpu->glInterface(),
-                   UniformMatrix4fv(uni.fVSLocation, arrayCount, false, matrices));
+};
+
+template<> struct set_uniform_matrix<3> {
+    inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
+        GR_GL_CALL(gli, UniformMatrix3fv(loc, cnt, false, m));
     }
-}
+};
+
+template<> struct set_uniform_matrix<4> {
+    inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
+        GR_GL_CALL(gli, UniformMatrix4fv(loc, cnt, false, m));
+    }
+};
 
 void GrGLProgramDataManager::setPathFragmentInputTransform(VaryingHandle u,
                                                            int components,
diff --git a/src/gpu/gl/GrGLProgramDataManager.h b/src/gpu/gl/GrGLProgramDataManager.h
index 2c92cec..c2cb8fc 100644
--- a/src/gpu/gl/GrGLProgramDataManager.h
+++ b/src/gpu/gl/GrGLProgramDataManager.h
@@ -61,8 +61,10 @@
     void set4fv(UniformHandle, int arrayCount, const float v[]) const override;
     // matrices are column-major, the first three upload a single matrix, the latter three upload
     // arrayCount matrices into a uniform array.
+    void setMatrix2f(UniformHandle, const float matrix[]) const override;
     void setMatrix3f(UniformHandle, const float matrix[]) const override;
     void setMatrix4f(UniformHandle, const float matrix[]) const override;
+    void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override;
     void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
     void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
 
@@ -97,6 +99,9 @@
 
     SkDEBUGCODE(void printUnused(const Uniform&) const;)
 
+    template<int N> inline void setMatrices(UniformHandle, int arrayCount,
+                                            const float matrices[]) const;
+
     SkTArray<Uniform, true> fUniforms;
     SkTArray<PathProcVarying, true> fPathProcVaryings;
     GrGLGpu* fGpu;
diff --git a/src/gpu/glsl/GrGLSL.h b/src/gpu/glsl/GrGLSL.h
index b13113a..12c1f1f 100644
--- a/src/gpu/glsl/GrGLSL.h
+++ b/src/gpu/glsl/GrGLSL.h
@@ -98,6 +98,8 @@
             return "vec3";
         case kVec4f_GrSLType:
             return "vec4";
+        case kMat22f_GrSLType:
+            return "mat2";
         case kMat33f_GrSLType:
             return "mat3";
         case kMat44f_GrSLType:
diff --git a/src/gpu/glsl/GrGLSLProgramDataManager.h b/src/gpu/glsl/GrGLSLProgramDataManager.h
index b059d46..e578e11 100644
--- a/src/gpu/glsl/GrGLSLProgramDataManager.h
+++ b/src/gpu/glsl/GrGLSLProgramDataManager.h
@@ -56,8 +56,10 @@
     virtual void set4fv(UniformHandle, int arrayCount, const float v[]) const = 0;
     // matrices are column-major, the first three upload a single matrix, the latter three upload
     // arrayCount matrices into a uniform array.
+    virtual void setMatrix2f(UniformHandle, const float matrix[]) const = 0;
     virtual void setMatrix3f(UniformHandle, const float matrix[]) const = 0;
     virtual void setMatrix4f(UniformHandle, const float matrix[]) const = 0;
+    virtual void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const = 0;
     virtual void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const = 0;
     virtual void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const = 0;
 
diff --git a/src/gpu/vk/GrVkProgramDataManager.cpp b/src/gpu/vk/GrVkProgramDataManager.cpp
index 732e937..f189097 100644
--- a/src/gpu/vk/GrVkProgramDataManager.cpp
+++ b/src/gpu/vk/GrVkProgramDataManager.cpp
@@ -209,81 +209,37 @@
     memcpy(buffer, v, arrayCount * 4 * sizeof(float));
 }
 
+void GrVkProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
+    this->setMatrices<2>(u, 1, matrix);
+}
+
+void GrVkProgramDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
+    this->setMatrices<2>(u, arrayCount, m);
+}
+
 void GrVkProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
-    const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat33f_GrSLType);
-    SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
-    SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
-    void* buffer;
-    if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
-        buffer = fVertexUniformData.get();
-    } else {
-        SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
-        buffer = fFragmentUniformData.get();
-    }
-
-    SkASSERT(sizeof(float) == 4);
-    buffer = static_cast<char*>(buffer) + uni.fOffset;
-    memcpy(buffer, &matrix[0], 3 * sizeof(float));
-    buffer = static_cast<char*>(buffer) + 4*sizeof(float);
-    memcpy(buffer, &matrix[3], 3 * sizeof(float));
-    buffer = static_cast<char*>(buffer) + 4*sizeof(float);
-    memcpy(buffer, &matrix[6], 3 * sizeof(float));
+    this->setMatrices<3>(u, 1, matrix);
 }
 
-void GrVkProgramDataManager::setMatrix3fv(UniformHandle u,
-                                          int arrayCount,
-                                          const float matrices[]) const {
-    const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat33f_GrSLType);
-    SkASSERT(arrayCount > 0);
-    SkASSERT(arrayCount <= uni.fArrayCount ||
-             (1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount));
-    SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
-
-    void* buffer;
-    if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
-        buffer = fVertexUniformData.get();
-    } else {
-        SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
-        buffer = fFragmentUniformData.get();
-    }
-    SkASSERT(sizeof(float) == 4);
-    buffer = static_cast<char*>(buffer)+uni.fOffset;
-    for (int i = 0; i < arrayCount; ++i) {
-        const float* matrix = &matrices[9 * i];
-        memcpy(buffer, &matrix[0], 3 * sizeof(float));
-        buffer = static_cast<char*>(buffer) + 4*sizeof(float);
-        memcpy(buffer, &matrix[3], 3 * sizeof(float));
-        buffer = static_cast<char*>(buffer) + 4*sizeof(float);
-        memcpy(buffer, &matrix[6], 3 * sizeof(float));
-        buffer = static_cast<char*>(buffer) + 4*sizeof(float);
-    }
+void GrVkProgramDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
+    this->setMatrices<3>(u, arrayCount, m);
 }
 
-
 void GrVkProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
-    const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat44f_GrSLType);
-    SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
-    SkASSERT(GrVkUniformHandler::kUniformBufferDescSet == uni.fSetNumber);
-    void* buffer;
-    if (GrVkUniformHandler::kVertexBinding == uni.fBinding) {
-        buffer = fVertexUniformData.get();
-    } else {
-        SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
-        buffer = fFragmentUniformData.get();
-    }
-    buffer = static_cast<char*>(buffer) + uni.fOffset;
-    SkASSERT(sizeof(float) == 4);
-    memcpy(buffer, matrix, 16 * sizeof(float));
+    this->setMatrices<4>(u, 1, matrix);
 }
 
-void GrVkProgramDataManager::setMatrix4fv(UniformHandle u,
-                                          int arrayCount,
-                                          const float matrices[]) const {
+void GrVkProgramDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
+    this->setMatrices<4>(u, arrayCount, m);
+}
+
+template<int N> struct set_uniform_matrix;
+
+template<int N> inline void GrVkProgramDataManager::setMatrices(UniformHandle u,
+                                                                   int arrayCount,
+                                                                   const float matrices[]) const {
     const Uniform& uni = fUniforms[u.toIndex()];
-    SkASSERT(uni.fType == kMat44f_GrSLType);
+    SkASSERT(uni.fType == kMat22f_GrSLType + (N - 2));
     SkASSERT(arrayCount > 0);
     SkASSERT(arrayCount <= uni.fArrayCount ||
              (1 == arrayCount && GrGLSLShaderVar::kNonArray == uni.fArrayCount));
@@ -296,11 +252,34 @@
         SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
         buffer = fFragmentUniformData.get();
     }
-    buffer = static_cast<char*>(buffer) + uni.fOffset;
-    SkASSERT(sizeof(float) == 4);
-    memcpy(buffer, matrices, arrayCount * 16 * sizeof(float));
+
+    set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices);
 }
 
+template<int N> struct set_uniform_matrix {
+    inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
+        GR_STATIC_ASSERT(sizeof(float) == 4);
+        buffer = static_cast<char*>(buffer) + uniformOffset;
+        for (int i = 0; i < count; ++i) {
+            const float* matrix = &matrices[N * N * i];
+            memcpy(buffer, &matrix[0], N * sizeof(float));
+            buffer = static_cast<char*>(buffer) + 4*sizeof(float);
+            memcpy(buffer, &matrix[3], N * sizeof(float));
+            buffer = static_cast<char*>(buffer) + 4*sizeof(float);
+            memcpy(buffer, &matrix[6], N * sizeof(float));
+            buffer = static_cast<char*>(buffer) + 4*sizeof(float);
+        }
+    }
+};
+
+template<> struct set_uniform_matrix<4> {
+    inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
+        GR_STATIC_ASSERT(sizeof(float) == 4);
+        buffer = static_cast<char*>(buffer) + uniformOffset;
+        memcpy(buffer, matrices, count * 16 * sizeof(float));
+    }
+};
+
 void GrVkProgramDataManager::uploadUniformBuffers(const GrVkGpu* gpu,
                                                   GrVkUniformBuffer* vertexBuffer,
                                                   GrVkUniformBuffer* fragmentBuffer) const {
diff --git a/src/gpu/vk/GrVkProgramDataManager.h b/src/gpu/vk/GrVkProgramDataManager.h
index 8006259..3baef0a 100644
--- a/src/gpu/vk/GrVkProgramDataManager.h
+++ b/src/gpu/vk/GrVkProgramDataManager.h
@@ -33,8 +33,10 @@
     void set4fv(UniformHandle, int arrayCount, const float v[]) const override;
     // matrices are column-major, the first two upload a single matrix, the latter two upload
     // arrayCount matrices into a uniform array.
+    void setMatrix2f(UniformHandle, const float matrix[]) const override;
     void setMatrix3f(UniformHandle, const float matrix[]) const override;
     void setMatrix4f(UniformHandle, const float matrix[]) const override;
+    void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override;
     void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
     void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
 
@@ -58,6 +60,9 @@
         );
     };
 
+    template<int N> inline void setMatrices(UniformHandle, int arrayCount,
+                                            const float matrices[]) const;
+
     uint32_t fVertexUniformSize;
     uint32_t fFragmentUniformSize;
 
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index 55b41ab..ac6da19 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -22,6 +22,7 @@
         0x7, // kVec2f_GrSLType
         0xF, // kVec3f_GrSLType
         0xF, // kVec4f_GrSLType
+        0x7, // kMat22f_GrSLType
         0xF, // kMat33f_GrSLType
         0xF, // kMat44f_GrSLType
         0x0, // Sampler2D_GrSLType, should never return this
@@ -32,10 +33,11 @@
     GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
     GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
     GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
-    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
-    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(5 == kMat22f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(7 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kAlignments) == kGrSLTypeCount);
     return kAlignments[type];
 }
@@ -44,12 +46,14 @@
     For non floating point type returns 0 */
 static inline uint32_t grsltype_to_vk_size(GrSLType type) {
     SkASSERT(GrSLTypeIsFloatType(type));
+    SkASSERT(kMat22f_GrSLType != type); // TODO: handle mat2 differences between std140 and std430.
     static const uint32_t kSizes[] = {
         0,                        // kVoid_GrSLType
         sizeof(float),            // kFloat_GrSLType
         2 * sizeof(float),        // kVec2f_GrSLType
         3 * sizeof(float),        // kVec3f_GrSLType
         4 * sizeof(float),        // kVec4f_GrSLType
+        8 * sizeof(float),        // kMat22f_GrSLType. TODO: this will be 4 * szof(float) on std430.
         12 * sizeof(float),       // kMat33f_GrSLType
         16 * sizeof(float),       // kMat44f_GrSLType
         0,                        // kSampler2D_GrSLType
@@ -66,15 +70,16 @@
     GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
     GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
     GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
-    GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
-    GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
-    GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
-    GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
-    GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
-    GR_STATIC_ASSERT(10 == kBool_GrSLType);
-    GR_STATIC_ASSERT(11 == kInt_GrSLType);
-    GR_STATIC_ASSERT(12 == kUint_GrSLType);
-    GR_STATIC_ASSERT(13 == kGrSLTypeCount);
+    GR_STATIC_ASSERT(5 == kMat22f_GrSLType);
+    GR_STATIC_ASSERT(6 == kMat33f_GrSLType);
+    GR_STATIC_ASSERT(7 == kMat44f_GrSLType);
+    GR_STATIC_ASSERT(8 == kSampler2D_GrSLType);
+    GR_STATIC_ASSERT(9 == kSamplerExternal_GrSLType);
+    GR_STATIC_ASSERT(10 == kSampler2DRect_GrSLType);
+    GR_STATIC_ASSERT(11 == kBool_GrSLType);
+    GR_STATIC_ASSERT(12 == kInt_GrSLType);
+    GR_STATIC_ASSERT(13 == kUint_GrSLType);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kSizes) == kGrSLTypeCount);
 }
 
 
@@ -87,6 +92,7 @@
                             int arrayCount) {
     uint32_t alignmentMask = grsltype_to_alignment_mask(type);
     // We want to use the std140 layout here, so we must make arrays align to 16 bytes.
+    SkASSERT(type != kMat22f_GrSLType); // TODO: support mat2.
     if (arrayCount) {
         alignmentMask = 0xF;
     }