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

Seems to be failing the dEQP-GLES2.functional.uniform_api tests relating to boolean arrays.

BUG=angleproject:1123

This reverts commit 892a6a4b17b35e89898be8b4605c1ee595d3ae13.

Change-Id: Ifc4ce3ca806ef88a02ac6f693334ac37ce098a88
Reviewed-on: https://chromium-review.googlesource.com/298520
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 81bbe76..30386f7 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -22,7 +22,6 @@
 #include "libANGLE/features.h"
 #include "libANGLE/renderer/Renderer.h"
 #include "libANGLE/renderer/ProgramImpl.h"
-#include "libANGLE/queryconversions.h"
 
 namespace gl
 {
@@ -47,133 +46,8 @@
     return subscript;
 }
 
-void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
-{
-    stream->writeInt(var.type);
-    stream->writeInt(var.precision);
-    stream->writeString(var.name);
-    stream->writeString(var.mappedName);
-    stream->writeInt(var.arraySize);
-    stream->writeInt(var.staticUse);
-    stream->writeString(var.structName);
-    ASSERT(var.fields.empty());
 }
 
-void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
-{
-    var->type       = stream->readInt<GLenum>();
-    var->precision  = stream->readInt<GLenum>();
-    var->name       = stream->readString();
-    var->mappedName = stream->readString();
-    var->arraySize  = stream->readInt<unsigned int>();
-    var->staticUse  = stream->readBool();
-    var->structName = stream->readString();
-}
-
-template <typename VarT>
-void DefineUniformBlockMembers(const std::vector<VarT> &fields,
-                               const std::string &prefix,
-                               int blockIndex,
-                               std::vector<LinkedUniform> *uniformsOut)
-{
-    for (const VarT &field : fields)
-    {
-        const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
-
-        if (field.isStruct())
-        {
-            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
-            {
-                const std::string uniformElementName =
-                    fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
-                DefineUniformBlockMembers(field.fields, uniformElementName, blockIndex,
-                                          uniformsOut);
-            }
-        }
-        else
-        {
-            // TODO(jmadill): record row-majorness?
-            // Block layout is recorded in the Impl.
-            LinkedUniform newUniform(field.type, field.precision, fieldName, field.arraySize,
-                                     blockIndex, sh::BlockMemberInfo::getDefaultBlockInfo());
-
-            // Since block uniforms have no location, we don't need to store them in the uniform
-            // locations list.
-            uniformsOut->push_back(newUniform);
-        }
-    }
-}
-
-// This simplified cast function doesn't need to worry about advanced concepts like
-// depth range values, or casting to bool.
-template <typename DestT, typename SrcT>
-DestT UniformStateQueryCast(SrcT value);
-
-// From-Float-To-Integer Casts
-template <>
-GLint UniformStateQueryCast(GLfloat value)
-{
-    return clampCast<GLint>(roundf(value));
-}
-
-template <>
-GLuint UniformStateQueryCast(GLfloat value)
-{
-    return clampCast<GLuint>(roundf(value));
-}
-
-// From-Integer-to-Integer Casts
-template <>
-GLint UniformStateQueryCast(GLuint value)
-{
-    return clampCast<GLint>(value);
-}
-
-template <>
-GLuint UniformStateQueryCast(GLint value)
-{
-    return clampCast<GLuint>(value);
-}
-
-// From-Boolean-to-Anything Casts
-template <>
-GLfloat UniformStateQueryCast(GLboolean value)
-{
-    return (value == GL_TRUE ? 1.0f : 0.0f);
-}
-
-template <>
-GLint UniformStateQueryCast(GLboolean value)
-{
-    return (value == GL_TRUE ? 1 : 0);
-}
-
-template <>
-GLuint UniformStateQueryCast(GLboolean value)
-{
-    return (value == GL_TRUE ? 1u : 0u);
-}
-
-// Default to static_cast
-template <typename DestT, typename SrcT>
-DestT UniformStateQueryCast(SrcT value)
-{
-    return static_cast<DestT>(value);
-}
-
-template <typename SrcT, typename DestT>
-void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
-{
-    const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(srcPointer);
-
-    for (int comp = 0; comp < components; ++comp)
-    {
-        dataOut[comp] = UniformStateQueryCast<DestT>(typedSrcPointer[comp]);
-    }
-}
-
-}  // anonymous namespace
-
 AttributeBindings::AttributeBindings()
 {
 }
@@ -288,68 +162,6 @@
     }
 }
 
-const LinkedUniform *Program::Data::getUniformByName(const std::string &name) const
-{
-    for (const LinkedUniform &linkedUniform : mUniforms)
-    {
-        if (linkedUniform.name == name)
-        {
-            return &linkedUniform;
-        }
-    }
-
-    return nullptr;
-}
-
-GLint Program::Data::getUniformLocation(const std::string &name) const
-{
-    size_t subscript     = GL_INVALID_INDEX;
-    std::string baseName = gl::ParseUniformName(name, &subscript);
-
-    for (size_t location = 0; location < mUniformLocations.size(); ++location)
-    {
-        const VariableLocation &uniformLocation = mUniformLocations[location];
-        const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
-
-        if (uniform.name == baseName)
-        {
-            if ((uniform.isArray() && uniformLocation.element == subscript) ||
-                (subscript == GL_INVALID_INDEX))
-            {
-                return static_cast<GLint>(location);
-            }
-        }
-    }
-
-    return -1;
-}
-
-GLuint Program::Data::getUniformIndex(const std::string &name) const
-{
-    size_t subscript     = GL_INVALID_INDEX;
-    std::string baseName = gl::ParseUniformName(name, &subscript);
-
-    // The app is not allowed to specify array indices other than 0 for arrays of basic types
-    if (subscript != 0 && subscript != GL_INVALID_INDEX)
-    {
-        return GL_INVALID_INDEX;
-    }
-
-    for (size_t index = 0; index < mUniforms.size(); index++)
-    {
-        const LinkedUniform &uniform = mUniforms[index];
-        if (uniform.name == baseName)
-        {
-            if (uniform.isArray() || subscript == GL_INVALID_INDEX)
-            {
-                return static_cast<GLuint>(index);
-            }
-        }
-    }
-
-    return GL_INVALID_INDEX;
-}
-
 Program::Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle)
     : mProgram(factory->createProgram(mData)),
       mValidated(false),
@@ -507,7 +319,6 @@
     }
 
     gatherTransformFeedbackVaryings(mergedVaryings);
-    mProgram->gatherUniformBlockInfo(&mData.mUniformBlocks, &mData.mUniforms);
 
     mLinked = true;
     return gl::Error(GL_NO_ERROR);
@@ -547,11 +358,10 @@
     mData.mAttributes.clear();
     mData.mActiveAttribLocationsMask.reset();
     mData.mTransformFeedbackVaryingVars.clear();
-    mData.mUniforms.clear();
-    mData.mUniformLocations.clear();
-    mData.mUniformBlocks.clear();
     mData.mOutputVariables.clear();
 
+    mProgram->reset();
+
     mValidated = false;
 
     mLinked = false;
@@ -605,66 +415,15 @@
     for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
     {
         sh::Attribute attrib;
-        LoadShaderVar(&stream, &attrib);
-        attrib.location = stream.readInt<int>();
+        attrib.type      = stream.readInt<GLenum>();
+        attrib.precision = stream.readInt<GLenum>();
+        attrib.name      = stream.readString();
+        attrib.arraySize = stream.readInt<GLint>();
+        attrib.location  = stream.readInt<int>();
+        attrib.staticUse = stream.readBool();
         mData.mAttributes.push_back(attrib);
     }
 
-    unsigned int uniformCount = stream.readInt<unsigned int>();
-    ASSERT(mData.mUniforms.empty());
-    for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
-    {
-        LinkedUniform uniform;
-        LoadShaderVar(&stream, &uniform);
-
-        uniform.blockIndex                 = stream.readInt<int>();
-        uniform.blockInfo.offset           = stream.readInt<int>();
-        uniform.blockInfo.arrayStride      = stream.readInt<int>();
-        uniform.blockInfo.matrixStride     = stream.readInt<int>();
-        uniform.blockInfo.isRowMajorMatrix = stream.readBool();
-
-        mData.mUniforms.push_back(uniform);
-    }
-
-    const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
-    ASSERT(mData.mUniformLocations.empty());
-    for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
-         uniformIndexIndex++)
-    {
-        VariableLocation variable;
-        stream.readString(&variable.name);
-        stream.readInt(&variable.element);
-        stream.readInt(&variable.index);
-
-        mData.mUniformLocations.push_back(variable);
-    }
-
-    unsigned int uniformBlockCount = stream.readInt<unsigned int>();
-    ASSERT(mData.mUniformBlocks.empty());
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
-         ++uniformBlockIndex)
-    {
-        UniformBlock uniformBlock;
-        stream.readString(&uniformBlock.name);
-        stream.readBool(&uniformBlock.isArray);
-        stream.readInt(&uniformBlock.arrayElement);
-        stream.readInt(&uniformBlock.dataSize);
-        stream.readBool(&uniformBlock.vertexStaticUse);
-        stream.readBool(&uniformBlock.fragmentStaticUse);
-
-        unsigned int numMembers = stream.readInt<unsigned int>();
-        for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
-        {
-            uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
-        }
-
-        // TODO(jmadill): Make D3D-only
-        stream.readInt(&uniformBlock.psRegisterIndex);
-        stream.readInt(&uniformBlock.vsRegisterIndex);
-
-        mData.mUniformBlocks.push_back(uniformBlock);
-    }
-
     stream.readInt(&mData.mTransformFeedbackBufferMode);
 
     unsigned int outputVarCount = stream.readInt<unsigned int>();
@@ -708,52 +467,12 @@
     stream.writeInt(mData.mAttributes.size());
     for (const sh::Attribute &attrib : mData.mAttributes)
     {
-        WriteShaderVar(&stream, attrib);
+        stream.writeInt(attrib.type);
+        stream.writeInt(attrib.precision);
+        stream.writeString(attrib.name);
+        stream.writeInt(attrib.arraySize);
         stream.writeInt(attrib.location);
-    }
-
-    stream.writeInt(mData.mUniforms.size());
-    for (const gl::LinkedUniform &uniform : mData.mUniforms)
-    {
-        WriteShaderVar(&stream, uniform);
-
-        // FIXME: referenced
-
-        stream.writeInt(uniform.blockIndex);
-        stream.writeInt(uniform.blockInfo.offset);
-        stream.writeInt(uniform.blockInfo.arrayStride);
-        stream.writeInt(uniform.blockInfo.matrixStride);
-        stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
-    }
-
-    stream.writeInt(mData.mUniformLocations.size());
-    for (const auto &variable : mData.mUniformLocations)
-    {
-        stream.writeString(variable.name);
-        stream.writeInt(variable.element);
-        stream.writeInt(variable.index);
-    }
-
-    stream.writeInt(mData.mUniformBlocks.size());
-    for (const UniformBlock &uniformBlock : mData.mUniformBlocks)
-    {
-        stream.writeString(uniformBlock.name);
-        stream.writeInt(uniformBlock.isArray);
-        stream.writeInt(uniformBlock.arrayElement);
-        stream.writeInt(uniformBlock.dataSize);
-
-        stream.writeInt(uniformBlock.vertexStaticUse);
-        stream.writeInt(uniformBlock.fragmentStaticUse);
-
-        stream.writeInt(uniformBlock.memberUniformIndexes.size());
-        for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes)
-        {
-            stream.writeInt(memberUniformIndex);
-        }
-
-        // TODO(jmadill): make D3D-only
-        stream.writeInt(uniformBlock.psRegisterIndex);
-        stream.writeInt(uniformBlock.vsRegisterIndex);
+        stream.writeInt(attrib.staticUse);
     }
 
     stream.writeInt(mData.mTransformFeedbackBufferMode);
@@ -1009,14 +728,13 @@
 {
     if (mLinked)
     {
-        // index must be smaller than getActiveUniformCount()
-        ASSERT(index < mData.mUniforms.size());
-        const LinkedUniform &uniform = mData.mUniforms[index];
+        ASSERT(index < mProgram->getUniforms().size());   // index must be smaller than getActiveUniformCount()
+        LinkedUniform *uniform = mProgram->getUniforms()[index];
 
         if (bufsize > 0)
         {
-            std::string string = uniform.name;
-            if (uniform.isArray())
+            std::string string = uniform->name;
+            if (uniform->isArray())
             {
                 string += "[0]";
             }
@@ -1030,8 +748,8 @@
             }
         }
 
-        *size = uniform.elementCount();
-        *type = uniform.type;
+        *size = uniform->elementCount();
+        *type = uniform->type;
     }
     else
     {
@@ -1054,7 +772,7 @@
 {
     if (mLinked)
     {
-        return static_cast<GLint>(mData.mUniforms.size());
+        return static_cast<GLint>(mProgram->getUniforms().size());
     }
     else
     {
@@ -1064,16 +782,17 @@
 
 GLint Program::getActiveUniformMaxLength()
 {
-    size_t maxLength = 0;
+    int maxLength = 0;
 
     if (mLinked)
     {
-        for (const LinkedUniform &uniform : mData.mUniforms)
+        unsigned int numUniforms = static_cast<unsigned int>(mProgram->getUniforms().size());
+        for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
         {
-            if (!uniform.name.empty())
+            if (!mProgram->getUniforms()[uniformIndex]->name.empty())
             {
-                size_t length = uniform.name.length() + 1u;
-                if (uniform.isArray())
+                int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1);
+                if (mProgram->getUniforms()[uniformIndex]->isArray())
                 {
                     length += 3;  // Counting in "[0]".
                 }
@@ -1082,13 +801,12 @@
         }
     }
 
-    return static_cast<GLint>(maxLength);
+    return maxLength;
 }
 
 GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
 {
-    ASSERT(static_cast<size_t>(index) < mData.mUniforms.size());
-    const gl::LinkedUniform &uniform = mData.mUniforms[index];
+    const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index];
     switch (pname)
     {
       case GL_UNIFORM_TYPE:         return static_cast<GLint>(uniform.type);
@@ -1108,165 +826,149 @@
 
 bool Program::isValidUniformLocation(GLint location) const
 {
-    ASSERT(rx::IsIntegerCastSafe<GLint>(mData.mUniformLocations.size()));
-    return (location >= 0 && static_cast<size_t>(location) < mData.mUniformLocations.size());
+    const auto &uniformIndices = mProgram->getUniformIndices();
+    ASSERT(rx::IsIntegerCastSafe<GLint>(uniformIndices.size()));
+    return (location >= 0 && uniformIndices.find(location) != uniformIndices.end());
 }
 
-const LinkedUniform &Program::getUniformByLocation(GLint location) const
+LinkedUniform *Program::getUniformByLocation(GLint location) const
 {
-    ASSERT(location >= 0 && static_cast<size_t>(location) < mData.mUniformLocations.size());
-    return mData.mUniforms[mData.mUniformLocations[location].index];
+    return mProgram->getUniformByLocation(location);
 }
 
-GLint Program::getUniformLocation(const std::string &name) const
+LinkedUniform *Program::getUniformByName(const std::string &name) const
 {
-    return mData.getUniformLocation(name);
+    return mProgram->getUniformByName(name);
 }
 
-GLuint Program::getUniformIndex(const std::string &name) const
+GLint Program::getUniformLocation(const std::string &name)
 {
-    return mData.getUniformIndex(name);
+    return mProgram->getUniformLocation(name);
+}
+
+GLuint Program::getUniformIndex(const std::string &name)
+{
+    return mProgram->getUniformIndex(name);
 }
 
 void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
 {
-    setUniformInternal(location, count * 1, v);
     mProgram->setUniform1fv(location, count, v);
 }
 
 void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
 {
-    setUniformInternal(location, count * 2, v);
     mProgram->setUniform2fv(location, count, v);
 }
 
 void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
 {
-    setUniformInternal(location, count * 3, v);
     mProgram->setUniform3fv(location, count, v);
 }
 
 void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
 {
-    setUniformInternal(location, count * 4, v);
     mProgram->setUniform4fv(location, count, v);
 }
 
 void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
 {
-    setUniformInternal(location, count * 1, v);
     mProgram->setUniform1iv(location, count, v);
 }
 
 void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
 {
-    setUniformInternal(location, count * 2, v);
     mProgram->setUniform2iv(location, count, v);
 }
 
 void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
 {
-    setUniformInternal(location, count * 3, v);
     mProgram->setUniform3iv(location, count, v);
 }
 
 void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
 {
-    setUniformInternal(location, count * 4, v);
     mProgram->setUniform4iv(location, count, v);
 }
 
 void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
 {
-    setUniformInternal(location, count * 1, v);
     mProgram->setUniform1uiv(location, count, v);
 }
 
 void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
 {
-    setUniformInternal(location, count * 2, v);
     mProgram->setUniform2uiv(location, count, v);
 }
 
 void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
 {
-    setUniformInternal(location, count * 3, v);
     mProgram->setUniform3uiv(location, count, v);
 }
 
 void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
 {
-    setUniformInternal(location, count * 4, v);
     mProgram->setUniform4uiv(location, count, v);
 }
 
 void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<2, 2>(location, count, transpose, v);
     mProgram->setUniformMatrix2fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<3, 3>(location, count, transpose, v);
     mProgram->setUniformMatrix3fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<4, 4>(location, count, transpose, v);
     mProgram->setUniformMatrix4fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<2, 3>(location, count, transpose, v);
     mProgram->setUniformMatrix2x3fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<2, 4>(location, count, transpose, v);
     mProgram->setUniformMatrix2x4fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<3, 2>(location, count, transpose, v);
     mProgram->setUniformMatrix3x2fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<3, 4>(location, count, transpose, v);
     mProgram->setUniformMatrix3x4fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<4, 2>(location, count, transpose, v);
     mProgram->setUniformMatrix4x2fv(location, count, transpose, v);
 }
 
 void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
 {
-    setMatrixUniformInternal<4, 3>(location, count, transpose, v);
     mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
 }
 
 void Program::getUniformfv(GLint location, GLfloat *v)
 {
-    getUniformInternal(location, v);
+    mProgram->getUniformfv(location, v);
 }
 
 void Program::getUniformiv(GLint location, GLint *v)
 {
-    getUniformInternal(location, v);
+    mProgram->getUniformiv(location, v);
 }
 
 void Program::getUniformuiv(GLint location, GLuint *v)
 {
-    getUniformInternal(location, v);
+    mProgram->getUniformuiv(location, v);
 }
 
 void Program::flagForDeletion()
@@ -1305,23 +1007,22 @@
 
 GLuint Program::getActiveUniformBlockCount()
 {
-    return static_cast<GLuint>(mData.mUniformBlocks.size());
+    return static_cast<GLuint>(mProgram->getUniformBlocks().size());
 }
 
 void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
 {
-    ASSERT(uniformBlockIndex <
-           mData.mUniformBlocks.size());  // index must be smaller than getActiveUniformBlockCount()
+    ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size());   // index must be smaller than getActiveUniformBlockCount()
 
-    const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
+    const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
 
     if (bufSize > 0)
     {
         std::string string = uniformBlock.name;
 
-        if (uniformBlock.isArray)
+        if (uniformBlock.isArrayElement())
         {
-            string += ArrayString(uniformBlock.arrayElement);
+            string += ArrayString(uniformBlock.elementIndex);
         }
 
         strncpy(uniformBlockName, string.c_str(), bufSize);
@@ -1336,10 +1037,9 @@
 
 void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
 {
-    ASSERT(uniformBlockIndex <
-           mData.mUniformBlocks.size());  // index must be smaller than getActiveUniformBlockCount()
+    ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size());   // index must be smaller than getActiveUniformBlockCount()
 
-    const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
+    const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
 
     switch (pname)
     {
@@ -1347,8 +1047,7 @@
         *params = static_cast<GLint>(uniformBlock.dataSize);
         break;
       case GL_UNIFORM_BLOCK_NAME_LENGTH:
-          *params =
-              static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArray ? 3 : 0));
+        *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
         break;
       case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
         *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
@@ -1362,10 +1061,10 @@
         }
         break;
       case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
-          *params = static_cast<GLint>(uniformBlock.vertexStaticUse);
+        *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
         break;
       case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
-          *params = static_cast<GLint>(uniformBlock.fragmentStaticUse);
+        *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
         break;
       default: UNREACHABLE();
     }
@@ -1377,16 +1076,17 @@
 
     if (mLinked)
     {
-        unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
+        unsigned int numUniformBlocks =
+            static_cast<unsigned int>(mProgram->getUniformBlocks().size());
         for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
         {
-            const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
+            const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
             if (!uniformBlock.name.empty())
             {
                 const int length = static_cast<int>(uniformBlock.name.length()) + 1;
 
                 // Counting in "[0]".
-                const int arrayLength = (uniformBlock.isArray ? 3 : 0);
+                const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
 
                 maxLength = std::max(length + arrayLength, maxLength);
             }
@@ -1398,32 +1098,12 @@
 
 GLuint Program::getUniformBlockIndex(const std::string &name)
 {
-    size_t subscript     = GL_INVALID_INDEX;
-    std::string baseName = gl::ParseUniformName(name, &subscript);
-
-    unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
-    for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
-    {
-        const gl::UniformBlock &uniformBlock = mData.mUniformBlocks[blockIndex];
-        if (uniformBlock.name == baseName)
-        {
-            const bool arrayElementZero =
-                (subscript == GL_INVALID_INDEX &&
-                 (!uniformBlock.isArray || uniformBlock.arrayElement == 0));
-            if (subscript == uniformBlock.arrayElement || arrayElementZero)
-            {
-                return blockIndex;
-            }
-        }
-    }
-
-    return GL_INVALID_INDEX;
+    return mProgram->getUniformBlockIndex(name);
 }
 
-const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const
+const UniformBlock *Program::getUniformBlockByIndex(GLuint index) const
 {
-    ASSERT(index < static_cast<GLuint>(mData.mUniformBlocks.size()));
-    return mData.mUniformBlocks[index];
+    return mProgram->getUniformBlockByIndex(index);
 }
 
 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
@@ -1563,17 +1243,17 @@
     return true;
 }
 
-bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
+bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps & /*caps*/) const
 {
     const std::vector<sh::Uniform> &vertexUniforms   = mData.mAttachedVertexShader->getUniforms();
     const std::vector<sh::Uniform> &fragmentUniforms = mData.mAttachedFragmentShader->getUniforms();
 
     // Check that uniforms defined in the vertex and fragment shaders are identical
-    std::map<std::string, LinkedUniform> linkedUniforms;
+    std::map<std::string, const sh::Uniform *> linkedUniforms;
 
     for (const sh::Uniform &vertexUniform : vertexUniforms)
     {
-        linkedUniforms[vertexUniform.name] = LinkedUniform(vertexUniform);
+        linkedUniforms[vertexUniform.name] = &vertexUniform;
     }
 
     for (const sh::Uniform &fragmentUniform : fragmentUniforms)
@@ -1581,45 +1261,19 @@
         auto entry = linkedUniforms.find(fragmentUniform.name);
         if (entry != linkedUniforms.end())
         {
-            LinkedUniform *vertexUniform   = &entry->second;
-            const std::string &uniformName = "uniform '" + vertexUniform->name + "'";
-            if (!linkValidateUniforms(infoLog, uniformName, *vertexUniform, fragmentUniform))
+            const sh::Uniform &vertexUniform = *entry->second;
+            const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
+            if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
             {
                 return false;
             }
         }
     }
 
-    // Flatten the uniforms list (nested fields) into a simple list (no nesting).
-    // Also check the maximum uniform vector and sampler counts.
-    if (!flattenUniformsAndCheckCaps(caps, infoLog))
-    {
-        return false;
-    }
-
-    indexUniforms();
-
+    // TODO(jmadill): check sampler uniforms with caps
     return true;
 }
 
-void Program::indexUniforms()
-{
-    for (size_t uniformIndex = 0; uniformIndex < mData.mUniforms.size(); uniformIndex++)
-    {
-        const gl::LinkedUniform &uniform = mData.mUniforms[uniformIndex];
-
-        for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
-        {
-            if (!uniform.isBuiltIn())
-            {
-                // Assign in-order uniform locations
-                mData.mUniformLocations.push_back(gl::VariableLocation(
-                    uniform.name, arrayIndex, static_cast<unsigned int>(uniformIndex)));
-            }
-        }
-    }
-}
-
 bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
 {
     if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
@@ -1799,8 +1453,6 @@
         }
     }
 
-    gatherInterfaceBlockInfo();
-
     return true;
 }
 
@@ -2078,288 +1730,4 @@
         }
     }
 }
-
-bool Program::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
-{
-    const gl::Shader *vertexShader = mData.getAttachedVertexShader();
-    VectorAndSamplerCount vsCounts;
-
-    for (const sh::Uniform &uniform : vertexShader->getUniforms())
-    {
-        if (uniform.staticUse)
-        {
-            vsCounts += flattenUniform(uniform, uniform.name);
-        }
-    }
-
-    if (vsCounts.vectorCount > caps.maxVertexUniformVectors)
-    {
-        infoLog << "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS ("
-                << caps.maxVertexUniformVectors << ").";
-        return false;
-    }
-
-    if (vsCounts.samplerCount > caps.maxVertexTextureImageUnits)
-    {
-        infoLog << "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS ("
-                << caps.maxVertexTextureImageUnits << ").";
-        return false;
-    }
-
-    const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
-    VectorAndSamplerCount fsCounts;
-
-    for (const sh::Uniform &uniform : fragmentShader->getUniforms())
-    {
-        if (uniform.staticUse)
-        {
-            fsCounts += flattenUniform(uniform, uniform.name);
-        }
-    }
-
-    if (fsCounts.vectorCount > caps.maxFragmentUniformVectors)
-    {
-        infoLog << "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS ("
-                << caps.maxFragmentUniformVectors << ").";
-        return false;
-    }
-
-    if (fsCounts.samplerCount > caps.maxTextureImageUnits)
-    {
-        infoLog << "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS ("
-                << caps.maxTextureImageUnits << ").";
-        return false;
-    }
-
-    return true;
-}
-
-Program::VectorAndSamplerCount Program::flattenUniform(const sh::ShaderVariable &uniform,
-                                                       const std::string &fullName)
-{
-    VectorAndSamplerCount vectorAndSamplerCount;
-
-    if (uniform.isStruct())
-    {
-        for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
-        {
-            const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
-
-            for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
-            {
-                const sh::ShaderVariable &field  = uniform.fields[fieldIndex];
-                const std::string &fieldFullName = (fullName + elementString + "." + field.name);
-
-                vectorAndSamplerCount += flattenUniform(field, fieldFullName);
-            }
-        }
-
-        return vectorAndSamplerCount;
-    }
-
-    // Not a struct
-    if (mData.getUniformByName(fullName) == nullptr)
-    {
-        gl::LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName,
-                                        uniform.arraySize, -1,
-                                        sh::BlockMemberInfo::getDefaultBlockInfo());
-        linkedUniform.staticUse = true;
-        mData.mUniforms.push_back(linkedUniform);
-    }
-
-    vectorAndSamplerCount.vectorCount =
-        (VariableRegisterCount(uniform.type) * uniform.elementCount());
-    vectorAndSamplerCount.samplerCount = (IsSamplerType(uniform.type) ? uniform.elementCount() : 0);
-
-    return vectorAndSamplerCount;
-}
-
-void Program::gatherInterfaceBlockInfo()
-{
-    std::set<std::string> visitedList;
-
-    const gl::Shader *vertexShader = mData.getAttachedVertexShader();
-
-    ASSERT(mData.mUniformBlocks.empty());
-    for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
-    {
-        // Only 'packed' blocks are allowed to be considered inacive.
-        if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
-            continue;
-
-        if (visitedList.count(vertexBlock.name) > 0)
-            continue;
-
-        defineUniformBlock(vertexBlock, GL_VERTEX_SHADER);
-        visitedList.insert(vertexBlock.name);
-    }
-
-    const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
-
-    for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
-    {
-        // Only 'packed' blocks are allowed to be considered inacive.
-        if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
-            continue;
-
-        if (visitedList.count(fragmentBlock.name) > 0)
-        {
-            for (gl::UniformBlock &block : mData.mUniformBlocks)
-            {
-                if (block.name == fragmentBlock.name)
-                {
-                    block.fragmentStaticUse = fragmentBlock.staticUse;
-                }
-            }
-
-            continue;
-        }
-
-        defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
-        visitedList.insert(fragmentBlock.name);
-    }
-}
-
-void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
-{
-    std::string baseName;
-    if (!interfaceBlock.instanceName.empty() && interfaceBlock.arraySize == 0)
-    {
-        baseName = interfaceBlock.instanceName;
-    }
-
-    int blockIndex                = static_cast<int>(mData.mUniformBlocks.size());
-    size_t firstBlockUniformIndex = mData.mUniforms.size();
-    DefineUniformBlockMembers(interfaceBlock.fields, baseName, blockIndex, &mData.mUniforms);
-    size_t lastBlockUniformIndex = mData.mUniforms.size();
-
-    std::vector<unsigned int> blockUniformIndexes;
-    for (size_t blockUniformIndex = firstBlockUniformIndex;
-         blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
-    {
-        blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
-    }
-
-    if (interfaceBlock.arraySize > 0)
-    {
-        for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
-        {
-            UniformBlock block(interfaceBlock.name, true, arrayElement);
-            block.memberUniformIndexes = blockUniformIndexes;
-
-            if (shaderType == GL_VERTEX_SHADER)
-            {
-                block.vertexStaticUse = interfaceBlock.staticUse;
-            }
-            else
-            {
-                ASSERT(shaderType == GL_FRAGMENT_SHADER);
-                block.fragmentStaticUse = interfaceBlock.staticUse;
-            }
-
-            mData.mUniformBlocks.push_back(block);
-        }
-    }
-    else
-    {
-        UniformBlock block(interfaceBlock.name, false, 0);
-        block.memberUniformIndexes = blockUniformIndexes;
-
-        if (shaderType == GL_VERTEX_SHADER)
-        {
-            block.vertexStaticUse = interfaceBlock.staticUse;
-        }
-        else
-        {
-            ASSERT(shaderType == GL_FRAGMENT_SHADER);
-            block.fragmentStaticUse = interfaceBlock.staticUse;
-        }
-
-        mData.mUniformBlocks.push_back(block);
-    }
-}
-
-template <typename T>
-void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
-{
-    const VariableLocation &locationInfo = mData.mUniformLocations[location];
-    LinkedUniform *linkedUniform         = &mData.mUniforms[locationInfo.index];
-    uint8_t *destPointer                 = linkedUniform->getDataPtrToElement(locationInfo.element);
-
-    if (VariableComponentType(linkedUniform->type) == GL_BOOL)
-    {
-        // Do a cast conversion for boolean types. From the spec:
-        // "The uniform is set to FALSE if the input value is 0 or 0.0f, and set to TRUE otherwise."
-        GLboolean *destAsBool = reinterpret_cast<GLboolean *>(destPointer);
-        for (GLsizei component = 0; component < count; ++component)
-        {
-            destAsBool[component] = (v[component] != static_cast<T>(0) ? GL_TRUE : GL_FALSE);
-        }
-    }
-    else
-    {
-        memcpy(destPointer, v, sizeof(T) * count);
-    }
-}
-
-template <size_t cols, size_t rows, typename T>
-void Program::setMatrixUniformInternal(GLint location,
-                                       GLsizei count,
-                                       GLboolean transpose,
-                                       const T *v)
-{
-    if (!transpose)
-    {
-        setUniformInternal(location, count * cols * rows, v);
-        return;
-    }
-
-    // Perform a transposing copy.
-    const VariableLocation &locationInfo = mData.mUniformLocations[location];
-    LinkedUniform *linkedUniform         = &mData.mUniforms[locationInfo.index];
-    T *destPtr = reinterpret_cast<T *>(linkedUniform->getDataPtrToElement(locationInfo.element));
-    for (size_t row = 0; row < rows; ++row)
-    {
-        for (size_t col = 0; col < cols; ++col)
-        {
-            destPtr[col * rows + row] = v[row * cols + col];
-        }
-    }
-}
-
-template <typename DestT>
-void Program::getUniformInternal(GLint location, DestT *dataOut) const
-{
-    const VariableLocation &locationInfo = mData.mUniformLocations[location];
-    const LinkedUniform &uniform         = mData.mUniforms[locationInfo.index];
-
-    const uint8_t *srcPointer = uniform.getDataPtrToElement(locationInfo.element);
-
-    GLenum componentType = VariableComponentType(uniform.type);
-    if (componentType == GLTypeToGLenum<DestT>::value)
-    {
-        memcpy(dataOut, srcPointer, uniform.getElementSize());
-        return;
-    }
-
-    int components = VariableComponentCount(uniform.type);
-
-    switch (componentType)
-    {
-        case GL_INT:
-            UniformStateQueryCastLoop<GLint>(dataOut, srcPointer, components);
-            break;
-        case GL_UNSIGNED_INT:
-            UniformStateQueryCastLoop<GLuint>(dataOut, srcPointer, components);
-            break;
-        case GL_BOOL:
-            UniformStateQueryCastLoop<GLboolean>(dataOut, srcPointer, components);
-            break;
-        case GL_FLOAT:
-            UniformStateQueryCastLoop<GLfloat>(dataOut, srcPointer, components);
-            break;
-        default:
-            UNREACHABLE();
-    }
-}
 }