Pass matrix packing qualifier data back from the shader translator to the GLES API.

TRAC #23271

Signed-off-by: Nicolas Capens
Signed-off-by: Shannon Woods
Authored-by: Jamie Madill
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index d117a30..6aab921 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -3435,19 +3435,23 @@
 
     if (!structure)
     {
-        output.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index));
+        const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
+        output.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index, isRowMajorMatrix));
     }
     else
     {
-        Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index);
+        Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index, false);
 
         int fieldIndex = index;
 
         for (size_t i = 0; i < structure->size(); i++)
         {
-            const TType &fieldType = *(*structure)[i].type;
+            TType fieldType = *(*structure)[i].type;
             const TString &fieldName = fieldType.getFieldName();
 
+            // make sure to copy matrix packing information
+            fieldType.setLayoutQualifier(type.getLayoutQualifier());
+
             declareUniformToList(fieldType, fieldName, fieldIndex, structUniform.fields);
             fieldIndex += fieldType.totalRegisterCount();
         }
diff --git a/src/compiler/Uniform.cpp b/src/compiler/Uniform.cpp
index 3cd3599..ff933f2 100644
--- a/src/compiler/Uniform.cpp
+++ b/src/compiler/Uniform.cpp
@@ -28,13 +28,14 @@
 {
 }
 
-Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
+Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex, bool isRowMajorMatrix)
 {
     this->type = type;
     this->precision = precision;
     this->name = name;
     this->arraySize = arraySize;
     this->registerIndex = registerIndex;
+    this->isRowMajorMatrix = isRowMajorMatrix;
 }
 
 BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
@@ -73,9 +74,6 @@
 {
     const size_t componentSize = 4;
 
-    // TODO: row major matrices
-    bool isRowMajorMatrix = false;
-
     for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
     {
         int arrayStride;
@@ -85,7 +83,7 @@
 
         if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
         {
-            const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
+            const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, uniform.isRowMajorMatrix);
             blockInfo.push_back(memberInfo);
 
             if (uniform.arraySize > 0)
@@ -95,8 +93,8 @@
 
             if (gl::IsMatrixType(uniform.type))
             {
-                const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
-                const int numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
+                const int componentGroups = (uniform.isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
+                const int numComponents = (uniform.isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
                 *currentOffset += matrixStride * (componentGroups - 1);
                 *currentOffset += numComponents;
             }
@@ -150,8 +148,6 @@
     const unsigned int registerSize = 4;
     const size_t componentSize = 4;
 
-    // TODO: row major matrices
-    bool isRowMajorMatrix = false;
     // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
     ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
     int matrixStride = 0;
@@ -164,7 +160,7 @@
 
         if (uniform.arraySize > 0)
         {
-            const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
+            const int componentGroups = (uniform.isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
             arrayStride = matrixStride * componentGroups;
         }
     }
@@ -194,9 +190,6 @@
 
     const size_t componentSize = 4;
 
-    // TODO: row major matrices
-    bool isRowMajorMatrix = false;
-
     // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
     ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
 
@@ -207,13 +200,13 @@
 
     if (gl::IsMatrixType(uniform.type))
     {
-        numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
+        numComponents = (uniform.isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
         baseAlignment = rx::roundUp(baseAlignment, 4u);
         matrixStride = baseAlignment;
 
         if (uniform.arraySize > 0)
         {
-            const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
+            const int componentGroups = (uniform.isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
             arrayStride = matrixStride * componentGroups;
         }
     }
diff --git a/src/compiler/Uniform.h b/src/compiler/Uniform.h
index ac0fdfd..a1a07ab 100644
--- a/src/compiler/Uniform.h
+++ b/src/compiler/Uniform.h
@@ -33,7 +33,7 @@
 
 struct Uniform
 {
-    Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex);
+    Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex, bool isRowMajorMatrix);
 
     GLenum type;
     GLenum precision;
@@ -41,6 +41,7 @@
     unsigned int arraySize;
 
     unsigned int registerIndex;
+    bool isRowMajorMatrix;
 
     std::vector<Uniform> fields;
 };
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index 2f91591..53f3d0e 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -2166,6 +2166,11 @@
     {
         infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", uniformName.c_str());
     }
+    else if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix)
+    {
+        infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
+        return false;
+    }
 
     const unsigned int numMembers = vertexUniform.fields.size();
     for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
@@ -2269,7 +2274,7 @@
                 {
                     const sh::Uniform &field = constant.fields[fieldIndex];
                     const std::string &uniformName = constant.name + arrayString(elementIndex) + "." + field.name;
-                    const sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, elementRegisterIndex);
+                    const sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, elementRegisterIndex, field.isRowMajorMatrix);
                     if (!defineUniform(shader, fieldUniform, infoLog))
                     {
                         return false;
@@ -2287,7 +2292,7 @@
                 const sh::Uniform &field = constant.fields[fieldIndex];
                 const std::string &uniformName = constant.name + "." + field.name;
 
-                sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, fieldRegisterIndex);
+                sh::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize, fieldRegisterIndex, field.isRowMajorMatrix);
                 fieldUniform.fields = field.fields;
 
                 if (!defineUniform(shader, fieldUniform, infoLog))