Fix register assignment for constant arrays

Constant arrays are allocated in the same 'register file' as the one
for per-program uniforms, to support dynamic indexing. While we had
a special case for that in OutputASM::registerType(), in registerIndex()
we were actually allocating them in the temporaries register file. This
led to assigning the same register index range twice, leading to
overwriting the per-program uniforms with constant array data in the
shader.

Bug: b/168060171
Change-Id: If42944d186ed1c1328a8d477edca4662aa1e8e54
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/48248
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index 9e9d885..dffa148 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -2918,6 +2918,20 @@
 			samplerRegister(operand); // Make sure the sampler is declared
 		}
 
+		const TQualifier qualifier = operand->getQualifier();
+		if(qualifier == EvqConstExpr && (!operand->getAsConstantUnion() || !operand->getAsConstantUnion()->getUnionArrayPointer()))
+		{
+			// Constant arrays are in the constant register file.
+			if(operand->isArray() && operand->getArraySize() > 1)
+			{
+				return uniformRegister(operand);
+			}
+			else
+			{
+				return temporaryRegister(operand);
+			}
+		}
+
 		switch(operand->getQualifier())
 		{
 		case EvqTemporary:           return temporaryRegister(operand);
diff --git a/tests/GLESUnitTests/unittests.cpp b/tests/GLESUnitTests/unittests.cpp
index 92987c6..f9bea45 100644
--- a/tests/GLESUnitTests/unittests.cpp
+++ b/tests/GLESUnitTests/unittests.cpp
@@ -1091,6 +1091,61 @@
 	Uninitialize();
 }
 
+TEST_F(SwiftShaderTest, TestMat4Uniform)
+{
+	Initialize(3, false);
+	const std::string vs = R"(#version 300 es
+	    precision highp float;
+	    uniform mat4 UniformMatrix;
+	    out vec4 color;
+	    void main()
+        {
+		    const vec4 pos[] = vec4[](
+		        vec4( 1.,  1., .0, 1.),
+		        vec4(-1.,  1., .0, 1.),
+		        vec4(-1., -1., .0, 1.),
+		        vec4( 1.,  1., .0, 1.),
+		        vec4(-1., -1., .0, 1.),
+		        vec4( 1., -1., .0, 1.));
+		        gl_Position = pos[gl_VertexID];
+		      color = vec4(vec3(UniformMatrix[0].xyz), 1.);
+	    }
+	)";
+	const std::string ps = R"(#version 300 es
+	    precision  highp float;
+	    in vec4 color;
+	    out vec4 fragColor;
+	    void main() 
+        {
+		    fragColor = color;
+	    })";
+	const ProgramHandles ph = createProgram(vs, ps);
+
+	glUseProgram(ph.program);
+	GLint location = glGetUniformLocation(ph.program, "UniformMatrix");
+	ASSERT_NE(-1, location);
+	constexpr float unit_mat[] = {
+		1., 0., 0., 0.,
+		0., 1., 0., 0.,
+		0., 0., 1., 0.,
+		0., 0., 0., 1.
+	};
+	glUniformMatrix4fv(location, 1, GL_FALSE, unit_mat);
+	glClearColor(0.0, 0.0, 0.0, 1.0);
+	glClear(GL_COLOR_BUFFER_BIT);
+	GLuint dummyvao = GL_NONE;
+	glGenVertexArrays(1, &dummyvao);
+	glBindVertexArray(dummyvao);
+	glDrawArrays(GL_TRIANGLES, 0, 6);
+
+	EXPECT_NO_GL_ERROR();
+
+	unsigned char red[4] = { 255, 0, 0, 255 };
+	expectFramebufferColor(red);
+
+	Uninitialize();
+}
+
 // Test sampling from a sampler in a struct as a function argument
 TEST_F(SwiftShaderTest, SamplerArrayInStructArrayAsFunctionArg)
 {