Error messages for uniform block validation

Many error messages related to uniform block validation were missing,
so there was no output message when linking failed.
Also, the rowMajor validation was missing and was also not set properly
when individual block members were overriding this layout qualifier.

Fixes:
dEQP-GLES3.functional.shaders.linkage.uniform.block.layout_qualifier_mismatch_5

Change-Id: I97309c3ead6e541d6cd9054ecfd29d08206de7da
Reviewed-on: https://swiftshader-review.googlesource.com/15808
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index df28913..2eb8329 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -103,14 +103,20 @@
 		int arrayStride;
 		int matrixStride;
 
-		getBlockLayoutInfo(type, type.getArraySize(), isRowMajor, &arrayStride, &matrixStride);
+		bool isVariableRowMajor = isRowMajor;
+		TLayoutMatrixPacking matrixPacking = type.getLayoutQualifier().matrixPacking;
+		if(matrixPacking != EmpUnspecified)
+		{
+			isVariableRowMajor = (matrixPacking == EmpRowMajor);
+		}
+		getBlockLayoutInfo(type, type.getArraySize(), isVariableRowMajor, &arrayStride, &matrixStride);
 
 		const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
 		                                 static_cast<int>(arrayStride * BytesPerComponent),
 		                                 static_cast<int>(matrixStride * BytesPerComponent),
-		                                 (matrixStride > 0) && isRowMajor);
+		                                 (matrixStride > 0) && isVariableRowMajor);
 
-		advanceOffset(type, type.getArraySize(), isRowMajor, arrayStride, matrixStride);
+		advanceOffset(type, type.getArraySize(), isVariableRowMajor, arrayStride, matrixStride);
 
 		return memberInfo;
 	}
diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp
index 0d37ed7..02846ee 100644
--- a/src/OpenGL/libGLESv2/Program.cpp
+++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -1867,14 +1867,17 @@
 		// validate blocks for the same member types
 		if(block1.fields.size() != block2.fields.size())
 		{
+			appendToInfoLog("Types for interface block '%s' differ between vertex and fragment shaders", block1.name.c_str());
 			return false;
 		}
 		if(block1.arraySize != block2.arraySize)
 		{
+			appendToInfoLog("Array sizes differ for interface block '%s' between vertex and fragment shaders", block1.name.c_str());
 			return false;
 		}
 		if(block1.layout != block2.layout || block1.isRowMajorLayout != block2.isRowMajorLayout)
 		{
+			appendToInfoLog("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", block1.name.c_str());
 			return false;
 		}
 		const size_t numBlockMembers = block1.fields.size();
@@ -1882,11 +1885,30 @@
 		{
 			const glsl::Uniform& member1 = shader1->activeUniforms[block1.fields[blockMemberIndex]];
 			const glsl::Uniform& member2 = shader2->activeUniforms[block2.fields[blockMemberIndex]];
-			if(member1.name != member2.name ||
-			   member1.arraySize != member2.arraySize ||
-			   member1.precision != member2.precision ||
-			   member1.type != member2.type)
+			if(member1.name != member2.name)
 			{
+				appendToInfoLog("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
+				                blockMemberIndex, block1.name.c_str(), member1.name.c_str(), member2.name.c_str());
+				return false;
+			}
+			if(member1.arraySize != member2.arraySize)
+			{
+				appendToInfoLog("Array sizes for %s differ between vertex and fragment shaders", member1.name.c_str());
+				return false;
+			}
+			if(member1.precision != member2.precision)
+			{
+				appendToInfoLog("Precisions for %s differ between vertex and fragment shaders", member1.name.c_str());
+				return false;
+			}
+			if(member1.type != member2.type)
+			{
+				appendToInfoLog("Types for %s differ between vertex and fragment shaders", member1.name.c_str());
+				return false;
+			}
+			if(member1.blockInfo.isRowMajorMatrix != member2.blockInfo.isRowMajorMatrix)
+			{
+				appendToInfoLog("Matrix packings for %s differ between vertex and fragment shaders", member1.name.c_str());
 				return false;
 			}
 		}