Commit 5ed74cfd by Geoff Lang

Fix uniform locations in ProgramGL.

ProgramGL was unable to handle uniform arrays and improperly set uniform locations. It now queries the driver for the location of each uniform and iterates over all array elements. BUG=angleproject:882 Change-Id: Iffe9d12944b2399f19f4a7823df2f535a430d6e3 Reviewed-on: https://chromium-review.googlesource.com/265724Tested-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 1623a1b9
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "libANGLE/renderer/gl/ProgramGL.h" #include "libANGLE/renderer/gl/ProgramGL.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/ShaderGL.h" #include "libANGLE/renderer/gl/ShaderGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h"
...@@ -135,11 +136,34 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog, ...@@ -135,11 +136,34 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog,
GLenum uniformType = GL_NONE; GLenum uniformType = GL_NONE;
mFunctions->getActiveUniform(mProgramID, i, uniformNameBuffer.size(), &uniformNameLength, &uniformSize, &uniformType, &uniformNameBuffer[0]); mFunctions->getActiveUniform(mProgramID, i, uniformNameBuffer.size(), &uniformNameLength, &uniformSize, &uniformType, &uniformNameBuffer[0]);
std::string uniformName(&uniformNameBuffer[0], uniformNameLength); std::string uniformName = gl::ParseUniformName(std::string(&uniformNameBuffer[0], uniformNameLength), nullptr);
for (size_t arrayIndex = 0; arrayIndex < static_cast<size_t>(uniformSize); arrayIndex++)
{
std::string locationName = uniformName;
if (uniformSize > 1)
{
locationName += "[" + Str(arrayIndex) + "]";
}
GLint location = mFunctions->getUniformLocation(mProgramID, locationName.c_str());
if (location >= 0)
{
// Make sure the uniform index array is large enough
if (static_cast<size_t>(location) >= mUniformIndex.size())
{
mUniformIndex.resize(location + 1);
}
mUniformIndex[location] = gl::VariableLocation(uniformName, arrayIndex, static_cast<unsigned int>(mUniforms.size()));
}
}
// ANGLE uses 0 to identify an non-array uniform.
unsigned int arraySize = (uniformSize > 1) ? static_cast<unsigned int>(uniformSize) : 0;
// TODO: determine uniform precision // TODO: determine uniform precision
mUniforms.push_back(new gl::LinkedUniform(uniformType, GL_NONE, uniformName, uniformSize, -1, sh::BlockMemberInfo::getDefaultBlockInfo())); mUniforms.push_back(new gl::LinkedUniform(uniformType, GL_NONE, uniformName, arraySize, -1, sh::BlockMemberInfo::getDefaultBlockInfo()));
mUniformIndex.push_back(gl::VariableLocation(uniformName, 0, i));
} }
// Query the attribute information // Query the attribute information
......
#include "ANGLETest.h" #include "ANGLETest.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_TYPED_TEST_CASE(UniformTest, ES2_D3D9, ES2_D3D11); ANGLE_TYPED_TEST_CASE(UniformTest, ES2_D3D9, ES2_D3D11, ES2_OPENGL);
template<typename T> template<typename T>
class UniformTest : public ANGLETest class UniformTest : public ANGLETest
...@@ -76,3 +76,67 @@ TYPED_TEST(UniformTest, GetUniformNoCurrentProgram) ...@@ -76,3 +76,67 @@ TYPED_TEST(UniformTest, GetUniformNoCurrentProgram)
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
EXPECT_EQ(1, i); EXPECT_EQ(1, i);
} }
TYPED_TEST(UniformTest, UniformArrayLocations)
{
const std::string vertexShader = SHADER_SOURCE
(
precision mediump float;
uniform float uPosition[4];
void main(void)
{
gl_Position = vec4(uPosition[0], uPosition[1], uPosition[2], uPosition[3]);
}
);
const std::string fragShader = SHADER_SOURCE
(
precision mediump float;
uniform float uColor[4];
void main(void)
{
gl_FragColor = vec4(uColor[0], uColor[1], uColor[2], uColor[3]);
}
);
GLuint program = CompileProgram(vertexShader, fragShader);
ASSERT_NE(program, 0u);
// Array index zero should be equivalent to the un-indexed uniform
EXPECT_NE(-1, glGetUniformLocation(program, "uPosition"));
EXPECT_EQ(glGetUniformLocation(program, "uPosition"), glGetUniformLocation(program, "uPosition[0]"));
EXPECT_NE(-1, glGetUniformLocation(program, "uColor"));
EXPECT_EQ(glGetUniformLocation(program, "uColor"), glGetUniformLocation(program, "uColor[0]"));
// All array uniform locations should be unique
GLint positionLocations[4] =
{
glGetUniformLocation(program, "uPosition[0]"),
glGetUniformLocation(program, "uPosition[1]"),
glGetUniformLocation(program, "uPosition[2]"),
glGetUniformLocation(program, "uPosition[3]"),
};
GLint colorLocations[4] =
{
glGetUniformLocation(program, "uColor[0]"),
glGetUniformLocation(program, "uColor[1]"),
glGetUniformLocation(program, "uColor[2]"),
glGetUniformLocation(program, "uColor[3]"),
};
for (size_t i = 0; i < 4; i++)
{
EXPECT_NE(-1, positionLocations[i]);
EXPECT_NE(-1, colorLocations[i]);
for (size_t j = i + 1; j < 4; j++)
{
EXPECT_NE(positionLocations[i], positionLocations[j]);
EXPECT_NE(colorLocations[i], colorLocations[j]);
}
}
glDeleteProgram(program);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment