Re^6-land "Move Uniform and UBO info to the gl::Program layer."

This data was previously stored entirely in the Impl level. Move
as much as possible to the GL level, using a read-only view in the
Impl level. Some information in D3D-specific, and should be stored
separately in the Impl.

This patch has a lot of refactoring that splits the D3D and GL info,
and moves as much validation as possible to the GL layer, where it
is shared between the back-ends.

Re-land with fix for dEQP unused uniforms. The fix involves storing
a local copy of all uniform data in the GL layer. This will also
let us validate sampler indexes during draw calls at the GL layer.

Re-re-land with a fix for multiply defined symbols on Clang.

Re-re-re-land with a fix for boolean uniforms and Uniform{1234}f.

Re^4-land with a fix for boolean uniform arrays and UBO uniforms.

Re^5-land with a fix for a test warning on Linux.

Re^6-land with a fix for transposed matrix uniform arrays.

BUG=angleproject:1123
TEST=end2end_tests, bots, dEQP GLES3.ubo and GLES2.uniform_api

Change-Id: Ie6fcde1c16eb05d67191b629338b88302a2563f5
Reviewed-on: https://chromium-review.googlesource.com/298971
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 3a70ae9..bae8389 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -115,68 +115,41 @@
     }
 
     // Query the uniform information
-    // TODO: A lot of this logic should be done at the gl::Program level
-    GLint activeUniformMaxLength = 0;
-    mFunctions->getProgramiv(mProgramID, GL_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformMaxLength);
-
-    std::vector<GLchar> uniformNameBuffer(activeUniformMaxLength);
-
-    GLint uniformCount = 0;
-    mFunctions->getProgramiv(mProgramID, GL_ACTIVE_UNIFORMS, &uniformCount);
-    for (GLint i = 0; i < uniformCount; i++)
+    ASSERT(mUniformRealLocationMap.empty());
+    const auto &uniforms = mData.getUniforms();
+    for (const gl::VariableLocation &entry : mData.getUniformLocations())
     {
-        GLsizei uniformNameLength = 0;
-        GLint uniformSize = 0;
-        GLenum uniformType = GL_NONE;
-        mFunctions->getActiveUniform(mProgramID, i, static_cast<GLsizei>(uniformNameBuffer.size()),
-                                     &uniformNameLength, &uniformSize, &uniformType,
-                                     &uniformNameBuffer[0]);
-
-        size_t subscript = 0;
-        std::string uniformName = gl::ParseUniformName(std::string(&uniformNameBuffer[0], uniformNameLength), &subscript);
-
-        bool isArray = uniformSize > 1 || subscript != GL_INVALID_INDEX;
-
-        for (size_t arrayIndex = 0; arrayIndex < static_cast<size_t>(uniformSize); arrayIndex++)
+        // From the spec:
+        // "Locations for sequential array indices are not required to be sequential."
+        const gl::LinkedUniform &uniform = uniforms[entry.index];
+        std::stringstream fullNameStr;
+        fullNameStr << uniform.name;
+        if (uniform.isArray())
         {
-            std::string locationName = uniformName;
-            if (isArray)
-            {
-                locationName += "[" + Str(static_cast<int>(arrayIndex)) + "]";
-            }
-
-            GLint location = mFunctions->getUniformLocation(mProgramID, locationName.c_str());
-            if (location >= 0)
-            {
-                mUniformIndex[location] =
-                    gl::VariableLocation(uniformName, static_cast<unsigned int>(arrayIndex),
-                                         static_cast<unsigned int>(mUniforms.size()));
-
-                // If the uniform is a sampler, track it in the sampler bindings array
-                if (gl::IsSamplerType(uniformType))
-                {
-                    SamplerLocation samplerLoc;
-                    samplerLoc.samplerIndex = mSamplerBindings.size();
-                    samplerLoc.arrayIndex = arrayIndex;
-                    mSamplerUniformMap[location] = samplerLoc;
-                }
-            }
+            fullNameStr << "[" << entry.element << "]";
         }
+        const std::string &fullName = fullNameStr.str();
 
-        // ANGLE uses 0 to identify an non-array uniform.
-        unsigned int arraySize = isArray ? static_cast<unsigned int>(uniformSize) : 0;
+        GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
+        mUniformRealLocationMap.push_back(realLocation);
+    }
 
-        // TODO: determine uniform precision
-        mUniforms.push_back(new gl::LinkedUniform(uniformType, GL_NONE, uniformName, arraySize, -1, sh::BlockMemberInfo::getDefaultBlockInfo()));
+    mUniformIndexToSamplerIndex.resize(mData.getUniforms().size(), GL_INVALID_INDEX);
+
+    for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
+    {
+        const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
+
+        if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
+            continue;
+
+        mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
 
         // If uniform is a sampler type, insert it into the mSamplerBindings array
-        if (gl::IsSamplerType(uniformType))
-        {
-            SamplerBindingGL samplerBinding;
-            samplerBinding.textureType = gl::SamplerTypeToTextureType(uniformType);
-            samplerBinding.boundTextureUnits.resize(uniformSize, 0);
-            mSamplerBindings.push_back(samplerBinding);
-        }
+        SamplerBindingGL samplerBinding;
+        samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
+        samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
+        mSamplerBindings.push_back(samplerBinding);
     }
 
     return LinkResult(true, gl::Error(GL_NO_ERROR));
@@ -191,59 +164,61 @@
 void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform1fv(location, count, v);
+    mFunctions->uniform1fv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform2fv(location, count, v);
+    mFunctions->uniform2fv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform3fv(location, count, v);
+    mFunctions->uniform3fv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform4fv(location, count, v);
+    mFunctions->uniform4fv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform1iv(location, count, v);
+    mFunctions->uniform1iv(uniLoc(location), count, v);
 
-    auto iter = mSamplerUniformMap.find(location);
-    if (iter != mSamplerUniformMap.end())
+    const gl::VariableLocation &locationEntry = mData.getUniformLocations()[location];
+
+    size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
+    if (samplerIndex != GL_INVALID_INDEX)
     {
-        const SamplerLocation &samplerLoc = iter->second;
-        std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerLoc.samplerIndex].boundTextureUnits;
+        std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
 
-        size_t copyCount = std::max<size_t>(count, boundTextureUnits.size() - samplerLoc.arrayIndex);
-        std::copy(v, v + copyCount, boundTextureUnits.begin() + samplerLoc.arrayIndex);
+        size_t copyCount =
+            std::max<size_t>(count, boundTextureUnits.size() - locationEntry.element);
+        std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
     }
 }
 
 void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform2iv(location, count, v);
+    mFunctions->uniform2iv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform3iv(location, count, v);
+    mFunctions->uniform3iv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform4iv(location, count, v);
+    mFunctions->uniform4iv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
@@ -255,88 +230,73 @@
 void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform2uiv(location, count, v);
+    mFunctions->uniform2uiv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform3uiv(location, count, v);
+    mFunctions->uniform3uiv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniform4uiv(location, count, v);
+    mFunctions->uniform4uiv(uniLoc(location), count, v);
 }
 
 void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix2fv(location, count, transpose, value);
+    mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix3fv(location, count, transpose, value);
+    mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix4fv(location, count, transpose, value);
+    mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix2x3fv(location, count, transpose, value);
+    mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix3x2fv(location, count, transpose, value);
+    mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix2x4fv(location, count, transpose, value);
+    mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix4x2fv(location, count, transpose, value);
+    mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix3x4fv(location, count, transpose, value);
+    mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
 }
 
 void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     mStateManager->useProgram(mProgramID);
-    mFunctions->uniformMatrix4x3fv(location, count, transpose, value);
-}
-
-void ProgramGL::getUniformfv(GLint location, GLfloat *params)
-{
-    mFunctions->getUniformfv(mProgramID, location, params);
-}
-
-void ProgramGL::getUniformiv(GLint location, GLint *params)
-{
-    mFunctions->getUniformiv(mProgramID, location, params);
-}
-
-void ProgramGL::getUniformuiv(GLint location, GLuint *params)
-{
-    mFunctions->getUniformuiv(mProgramID, location, params);
+    mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
 }
 
 bool ProgramGL::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
@@ -347,10 +307,9 @@
 
 void ProgramGL::reset()
 {
-    ProgramImpl::reset();
-
-    mSamplerUniformMap.clear();
+    mUniformRealLocationMap.clear();
     mSamplerBindings.clear();
+    mUniformIndexToSamplerIndex.clear();
 }
 
 GLuint ProgramGL::getProgramID() const
@@ -363,4 +322,9 @@
     return mSamplerBindings;
 }
 
+void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> * /*uniformBlocks*/,
+                                       std::vector<gl::LinkedUniform> * /*uniforms*/)
+{
+    // TODO(jmadill): Gather uniform block layout info, and data sizes.
+}
 }