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)
{