Adding NxM matrices uniform support

Added NxM matrices related functions
and entries to Program and utilities.

Change-Id: I5839c21cb3a9dc469fca4c553a0b5f97e0ad48bf
Reviewed-on: https://swiftshader-review.googlesource.com/3105
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Program.cpp b/src/OpenGL/libGLESv2/Program.cpp
index c33bc33..cf7a47a 100644
--- a/src/OpenGL/libGLESv2/Program.cpp
+++ b/src/OpenGL/libGLESv2/Program.cpp
@@ -884,9 +884,15 @@
 				  case GL_FLOAT_VEC2: applyUniform2fv(location, size, f);       break;

 				  case GL_FLOAT_VEC3: applyUniform3fv(location, size, f);       break;

 				  case GL_FLOAT_VEC4: applyUniform4fv(location, size, f);       break;

-				  case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, size, f); break;

-				  case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, size, f); break;

-				  case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, size, f); break;

+				  case GL_FLOAT_MAT2:   applyUniformMatrix2fv(location, size, f);   break;

+				  case GL_FLOAT_MAT2x3: applyUniformMatrix2x3fv(location, size, f); break;

+				  case GL_FLOAT_MAT2x4: applyUniformMatrix2x4fv(location, size, f); break;

+				  case GL_FLOAT_MAT3x2: applyUniformMatrix3x2fv(location, size, f); break;

+				  case GL_FLOAT_MAT3:   applyUniformMatrix3fv(location, size, f);   break;

+				  case GL_FLOAT_MAT3x4: applyUniformMatrix3x4fv(location, size, f); break;

+				  case GL_FLOAT_MAT4x2: applyUniformMatrix4x2fv(location, size, f); break;

+				  case GL_FLOAT_MAT4x3: applyUniformMatrix4x3fv(location, size, f); break;

+				  case GL_FLOAT_MAT4:   applyUniformMatrix4fv(location, size, f);   break;

 				  case GL_SAMPLER_2D:

 				  case GL_SAMPLER_CUBE:

 				  case GL_SAMPLER_EXTERNAL_OES:

@@ -1511,6 +1517,60 @@
 		return true;

 	}

 

+	bool Program::applyUniformMatrix2x3fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2]; matrix[i][0][3] = 0;

+			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];	matrix[i][1][2] = value[5]; matrix[i][1][3] = 0;

+

+			value += 6;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniformMatrix2x4fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2]; matrix[i][0][3] = value[3];

+			matrix[i][1][0] = value[4];	matrix[i][1][1] = value[5];	matrix[i][1][2] = value[6]; matrix[i][1][3] = value[7];

+

+			value += 8;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

 	bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)

 	{

 		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];

@@ -1539,6 +1599,62 @@
 		return true;

 	}

 

+	bool Program::applyUniformMatrix3x2fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;

+			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;

+			matrix[i][2][0] = value[4];	matrix[i][2][1] = value[5];	matrix[i][2][2] = 0; matrix[i][2][3] = 0;

+

+			value += 6;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniformMatrix3x4fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2]; 	matrix[i][0][3] = value[3];

+			matrix[i][1][0] = value[4];	matrix[i][1][1] = value[5];	matrix[i][1][2] = value[6]; 	matrix[i][1][3] = value[7];

+			matrix[i][2][0] = value[8];	matrix[i][2][1] = value[9];	matrix[i][2][2] = value[10];	matrix[i][2][3] = value[11];

+

+			value += 12;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

 	bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)

 	{

 		Uniform *targetUniform = uniforms[uniformIndex[location].index];

@@ -1556,6 +1672,64 @@
 		return true;

 	}

 

+	bool Program::applyUniformMatrix4x2fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;

+			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;

+			matrix[i][2][0] = value[4];	matrix[i][2][1] = value[5];	matrix[i][2][2] = 0; matrix[i][2][3] = 0;

+			matrix[i][3][0] = value[6];	matrix[i][3][1] = value[7];	matrix[i][3][2] = 0; matrix[i][3][3] = 0;

+

+			value += 8;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

+	bool Program::applyUniformMatrix4x3fv(GLint location, GLsizei count, const GLfloat *value)

+	{

+		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];

+

+		for(int i = 0; i < count; i++)

+		{

+			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];  matrix[i][0][2] = value[2];  matrix[i][0][3] = 0;

+			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];  matrix[i][1][2] = value[5];  matrix[i][1][3] = 0;

+			matrix[i][2][0] = value[6];	matrix[i][2][1] = value[7];  matrix[i][2][2] = value[8];  matrix[i][2][3] = 0;

+			matrix[i][3][0] = value[9];	matrix[i][3][1] = value[10]; matrix[i][3][2] = value[11]; matrix[i][3][3] = 0;

+

+			value += 12;

+		}

+

+		Uniform *targetUniform = uniforms[uniformIndex[location].index];

+

+		if(targetUniform->psRegisterIndex != -1)

+		{

+			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		if(targetUniform->vsRegisterIndex != -1)

+		{

+			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());

+		}

+

+		return true;

+	}

+

 	bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)

 	{

 		float vector[MAX_UNIFORM_VECTORS][4];

diff --git a/src/OpenGL/libGLESv2/Program.h b/src/OpenGL/libGLESv2/Program.h
index 5964d18..db9aafa 100644
--- a/src/OpenGL/libGLESv2/Program.h
+++ b/src/OpenGL/libGLESv2/Program.h
@@ -160,8 +160,14 @@
 		bool applyUniform3fv(GLint location, GLsizei count, const GLfloat *v);

 		bool applyUniform4fv(GLint location, GLsizei count, const GLfloat *v);

 		bool applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix2x3fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix2x4fv(GLint location, GLsizei count, const GLfloat *value);

 		bool applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix3x2fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix3x4fv(GLint location, GLsizei count, const GLfloat *value);

 		bool applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix4x2fv(GLint location, GLsizei count, const GLfloat *value);

+		bool applyUniformMatrix4x3fv(GLint location, GLsizei count, const GLfloat *value);

 		bool applyUniform1iv(GLint location, GLsizei count, const GLint *v);

 		bool applyUniform2iv(GLint location, GLsizei count, const GLint *v);

 		bool applyUniform3iv(GLint location, GLsizei count, const GLint *v);

diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 86f0c51..58c0e17 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -47,8 +47,17 @@
 		case GL_INT_VEC4:

 		case GL_FLOAT_MAT2:

 			return 4;

+		case GL_FLOAT_MAT2x3:

+		case GL_FLOAT_MAT3x2:

+			return 6;

+		case GL_FLOAT_MAT2x4:

+		case GL_FLOAT_MAT4x2:

+			return 8;

 		case GL_FLOAT_MAT3:

 			return 9;

+		case GL_FLOAT_MAT3x4:

+		case GL_FLOAT_MAT4x3:

+			return 12;

 		case GL_FLOAT_MAT4:

 			return 16;

 		default:

@@ -72,8 +81,14 @@
 		case GL_FLOAT_VEC3:

 		case GL_FLOAT_VEC4:

 		case GL_FLOAT_MAT2:

+		case GL_FLOAT_MAT2x3:

+		case GL_FLOAT_MAT2x4:

 		case GL_FLOAT_MAT3:

+		case GL_FLOAT_MAT3x2:

+		case GL_FLOAT_MAT3x4:

 		case GL_FLOAT_MAT4:

+		case GL_FLOAT_MAT4x2:

+		case GL_FLOAT_MAT4x3:

 			return GL_FLOAT;

 		case GL_INT:

 		case GL_SAMPLER_2D:

@@ -127,10 +142,16 @@
 		case GL_SAMPLER_3D_OES:

 			return 1;

 		case GL_FLOAT_MAT2:

+		case GL_FLOAT_MAT3x2:

+		case GL_FLOAT_MAT4x2:

 			return 2;

 		case GL_FLOAT_MAT3:

+		case GL_FLOAT_MAT2x3:

+		case GL_FLOAT_MAT4x3:

 			return 3;

 		case GL_FLOAT_MAT4:

+		case GL_FLOAT_MAT2x4:

+		case GL_FLOAT_MAT3x4:

 			return 4;

 		default:

 			UNREACHABLE();

@@ -153,16 +174,22 @@
 		case GL_FLOAT_VEC2:

 		case GL_INT_VEC2:

 		case GL_FLOAT_MAT2:

+		case GL_FLOAT_MAT2x3:

+		case GL_FLOAT_MAT2x4:

 			return 2;

 		case GL_INT_VEC3:

 		case GL_FLOAT_VEC3:

 		case GL_BOOL_VEC3:

 		case GL_FLOAT_MAT3:

+		case GL_FLOAT_MAT3x2:

+		case GL_FLOAT_MAT3x4:

 			return 3;

 		case GL_BOOL_VEC4:

 		case GL_FLOAT_VEC4:

 		case GL_INT_VEC4:

 		case GL_FLOAT_MAT4:

+		case GL_FLOAT_MAT4x2:

+		case GL_FLOAT_MAT4x3:

 			return 4;

 		default:

 			UNREACHABLE();