Revert "Re-land "Move sampler validation to the GL layer.""

Build failure on Linux:

In file included from ../../third_party/angle/src/tests/gl_tests/UniformTest.cpp:7:
In file included from ../../third_party/angle/src/tests/test_utils/ANGLETest.h:10:
../../testing/gtest/include/gtest/gtest.h:1392:16: error: comparison of integers of different signs: 'const int' and 'const unsigned int' [-Werror,-Wsign-compare]
  if (expected == actual) {
      ~~~~~~~~ ^  ~~~~~~
../../testing/gtest/include/gtest/gtest.h:1422:12: note: in instantiation of function template specialization 'testing::internal::CmpHelperEQ<int, unsigned int>' requested here
    return CmpHelperEQ(expected_expression, actual_expression, expected,
           ^
../../third_party/angle/src/tests/gl_tests/UniformTest.cpp:487:5: note: in instantiation of function template specialization 'testing::internal::EqHelper<false>::Compare<int, unsigned int>' requested here
    EXPECT_EQ(GL_SAMPLER_2D, type);
    ^

BUG=angleproject:1123

This reverts commit 6cbf4385280c4c1dd97f0882ecb18dbc4c341fd4.

Change-Id: I95279b37d253e3ea78faa53f3773f2dc3d17df95
Reviewed-on: https://chromium-review.googlesource.com/302030
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 14a50ba..6922adf 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -174,17 +174,6 @@
     }
 }
 
-bool UniformInList(const std::vector<LinkedUniform> &list, const std::string &name)
-{
-    for (const LinkedUniform &uniform : list)
-    {
-        if (uniform.name == name)
-            return true;
-    }
-
-    return false;
-}
-
 }  // anonymous namespace
 
 AttributeBindings::AttributeBindings()
@@ -370,8 +359,7 @@
       mDeleteStatus(false),
       mRefCount(0),
       mResourceManager(manager),
-      mHandle(handle),
-      mSamplerUniformRange(0, 0)
+      mHandle(handle)
 {
     ASSERT(mProgram);
 
@@ -686,15 +674,12 @@
     {
         int locationIndex = stream.readInt<int>();
         VariableLocation locationData;
-        stream.readInt(&locationData.element);
-        stream.readInt(&locationData.index);
-        stream.readString(&locationData.name);
+        locationData.element                  = stream.readInt<unsigned int>();
+        locationData.index                    = stream.readInt<unsigned int>();
+        locationData.name                     = stream.readString();
         mData.mOutputVariables[locationIndex] = locationData;
     }
 
-    stream.readInt(&mSamplerUniformRange.start);
-    stream.readInt(&mSamplerUniformRange.end);
-
     rx::LinkResult result = mProgram->load(mInfoLog, &stream);
     if (result.error.isError() || !result.linkSuccess)
     {
@@ -784,9 +769,6 @@
         stream.writeString(outputPair.second.name);
     }
 
-    stream.writeInt(mSamplerUniformRange.start);
-    stream.writeInt(mSamplerUniformRange.end);
-
     gl::Error error = mProgram->save(&stream);
     if (error.isError())
     {
@@ -1315,78 +1297,7 @@
 
 bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
 {
-    // Skip cache if we're using an infolog, so we get the full error.
-    // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
-    if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
-    {
-        return mCachedValidateSamplersResult.value();
-    }
-
-    if (mTextureUnitTypesCache.empty())
-    {
-        mTextureUnitTypesCache.resize(caps.maxCombinedTextureImageUnits, GL_NONE);
-    }
-    else
-    {
-        std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
-    }
-
-    // if any two active samplers in a program are of different types, but refer to the same
-    // texture image unit, and this is the current program, then ValidateProgram will fail, and
-    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
-    for (unsigned int samplerIndex = mSamplerUniformRange.start;
-         samplerIndex < mSamplerUniformRange.end; ++samplerIndex)
-    {
-        const LinkedUniform &uniform = mData.mUniforms[samplerIndex];
-        ASSERT(uniform.isSampler());
-
-        if (!uniform.staticUse)
-            continue;
-
-        const GLuint *dataPtr = reinterpret_cast<const GLuint *>(uniform.getDataPtrToElement(0));
-        GLenum textureType    = SamplerTypeToTextureType(uniform.type);
-
-        for (unsigned int arrayElement = 0; arrayElement < uniform.elementCount(); ++arrayElement)
-        {
-            GLuint textureUnit = dataPtr[arrayElement];
-
-            if (textureUnit >= caps.maxCombinedTextureImageUnits)
-            {
-                if (infoLog)
-                {
-                    (*infoLog) << "Sampler uniform (" << textureUnit
-                               << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
-                               << caps.maxCombinedTextureImageUnits << ")";
-                }
-
-                mCachedValidateSamplersResult = false;
-                return false;
-            }
-
-            if (mTextureUnitTypesCache[textureUnit] != GL_NONE)
-            {
-                if (textureType != mTextureUnitTypesCache[textureUnit])
-                {
-                    if (infoLog)
-                    {
-                        (*infoLog) << "Samplers of conflicting types refer to the same texture "
-                                      "image unit ("
-                                   << textureUnit << ").";
-                    }
-
-                    mCachedValidateSamplersResult = false;
-                    return false;
-                }
-            }
-            else
-            {
-                mTextureUnitTypesCache[textureUnit] = textureType;
-            }
-        }
-    }
-
-    mCachedValidateSamplersResult = true;
-    return true;
+    return mProgram->validateSamplers(infoLog, caps);
 }
 
 bool Program::isValidated() const
@@ -2175,13 +2086,11 @@
     const gl::Shader *vertexShader = mData.getAttachedVertexShader();
     VectorAndSamplerCount vsCounts;
 
-    std::vector<LinkedUniform> samplerUniforms;
-
     for (const sh::Uniform &uniform : vertexShader->getUniforms())
     {
         if (uniform.staticUse)
         {
-            vsCounts += flattenUniform(uniform, uniform.name, &samplerUniforms);
+            vsCounts += flattenUniform(uniform, uniform.name);
         }
     }
 
@@ -2206,7 +2115,7 @@
     {
         if (uniform.staticUse)
         {
-            fsCounts += flattenUniform(uniform, uniform.name, &samplerUniforms);
+            fsCounts += flattenUniform(uniform, uniform.name);
         }
     }
 
@@ -2224,18 +2133,11 @@
         return false;
     }
 
-    mSamplerUniformRange.start = static_cast<unsigned int>(mData.mUniforms.size());
-    mSamplerUniformRange.end =
-        mSamplerUniformRange.start + static_cast<unsigned int>(samplerUniforms.size());
-
-    mData.mUniforms.insert(mData.mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
-
     return true;
 }
 
 Program::VectorAndSamplerCount Program::flattenUniform(const sh::ShaderVariable &uniform,
-                                                       const std::string &fullName,
-                                                       std::vector<LinkedUniform> *samplerUniforms)
+                                                       const std::string &fullName)
 {
     VectorAndSamplerCount vectorAndSamplerCount;
 
@@ -2250,7 +2152,7 @@
                 const sh::ShaderVariable &field  = uniform.fields[fieldIndex];
                 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
 
-                vectorAndSamplerCount += flattenUniform(field, fieldFullName, samplerUniforms);
+                vectorAndSamplerCount += flattenUniform(field, fieldFullName);
             }
         }
 
@@ -2258,28 +2160,18 @@
     }
 
     // Not a struct
-    bool isSampler = IsSamplerType(uniform.type);
-    if (!UniformInList(mData.getUniforms(), fullName) && !UniformInList(*samplerUniforms, fullName))
+    if (mData.getUniformByName(fullName) == nullptr)
     {
         gl::LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName,
                                         uniform.arraySize, -1,
                                         sh::BlockMemberInfo::getDefaultBlockInfo());
         linkedUniform.staticUse = true;
-
-        // Store sampler uniforms separately, so we'll append them to the end of the list.
-        if (isSampler)
-        {
-            samplerUniforms->push_back(linkedUniform);
-        }
-        else
-        {
-            mData.mUniforms.push_back(linkedUniform);
-        }
+        mData.mUniforms.push_back(linkedUniform);
     }
 
-    unsigned int elementCount          = uniform.elementCount();
-    vectorAndSamplerCount.vectorCount  = (VariableRegisterCount(uniform.type) * elementCount);
-    vectorAndSamplerCount.samplerCount = (isSampler ? elementCount : 0);
+    vectorAndSamplerCount.vectorCount =
+        (VariableRegisterCount(uniform.type) * uniform.elementCount());
+    vectorAndSamplerCount.samplerCount = (IsSamplerType(uniform.type) ? uniform.elementCount() : 0);
 
     return vectorAndSamplerCount;
 }
@@ -2402,12 +2294,6 @@
     }
     else
     {
-        // Invalide the validation cache if we modify the sampler data.
-        if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * count) != 0)
-        {
-            mCachedValidateSamplersResult.reset();
-        }
-
         memcpy(destPointer, v, sizeof(T) * count);
     }
 }
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 6e9d682..3dd7c46 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -10,6 +10,13 @@
 #ifndef LIBANGLE_PROGRAM_H_
 #define LIBANGLE_PROGRAM_H_
 
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
 #include <GLES2/gl2.h>
 #include <GLSLANG/ShaderLang.h>
 
@@ -18,15 +25,6 @@
 #include <string>
 #include <vector>
 
-#include "common/angleutils.h"
-#include "common/mathutil.h"
-#include "common/Optional.h"
-
-#include "libANGLE/angletypes.h"
-#include "libANGLE/Constants.h"
-#include "libANGLE/Error.h"
-#include "libANGLE/RefCountObject.h"
-
 namespace rx
 {
 class ImplFactory;
@@ -217,11 +215,6 @@
         std::vector<sh::Attribute> mAttributes;
         std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
 
-        // Uniforms are sorted in order:
-        //  1. Non-sampler uniforms
-        //  2. Sampler uniforms
-        //  3. Uniform block uniforms
-        // This makes sampler validation easier, since we don't need a separate list.
         std::vector<LinkedUniform> mUniforms;
         std::vector<VariableLocation> mUniformLocations;
         std::vector<UniformBlock> mUniformBlocks;
@@ -391,8 +384,7 @@
     };
 
     VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
-                                         const std::string &fullName,
-                                         std::vector<LinkedUniform> *samplerUniforms);
+                                         const std::string &fullName);
 
     void gatherInterfaceBlockInfo();
     void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
@@ -422,11 +414,6 @@
     const GLuint mHandle;
 
     InfoLog mInfoLog;
-
-    // Cache for sampler validation
-    Optional<bool> mCachedValidateSamplersResult;
-    std::vector<GLenum> mTextureUnitTypesCache;
-    RangeUI mSamplerUniformRange;
 };
 }
 
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index d51015a..752f995 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -633,7 +633,6 @@
 {
     const auto it = mSamplerTextures.find(type);
     ASSERT(it != mSamplerTextures.end());
-    ASSERT(sampler < it->second.size());
     return it->second[sampler].get();
 }
 
@@ -641,7 +640,6 @@
 {
     const auto it = mSamplerTextures.find(type);
     ASSERT(it != mSamplerTextures.end());
-    ASSERT(sampler < it->second.size());
     return it->second[sampler].id();
 }
 
diff --git a/src/libANGLE/Uniform.h b/src/libANGLE/Uniform.h
index 1b21825..040c978 100644
--- a/src/libANGLE/Uniform.h
+++ b/src/libANGLE/Uniform.h
@@ -64,7 +64,6 @@
 
     std::vector<unsigned int> memberUniformIndexes;
 
-    // TODO(jmadill): Make D3D-only.
     unsigned int psRegisterIndex;
     unsigned int vsRegisterIndex;
 };
diff --git a/src/libANGLE/renderer/ProgramImpl.h b/src/libANGLE/renderer/ProgramImpl.h
index a47b18e..47fb9be 100644
--- a/src/libANGLE/renderer/ProgramImpl.h
+++ b/src/libANGLE/renderer/ProgramImpl.h
@@ -66,6 +66,10 @@
     virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
     virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
 
+    // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to
+    // determine if they can be removed from this interface.
+    virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0;
+
     // Gather uniform block active uniform indices, and uniform block offset info.
     virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
                                         std::vector<gl::LinkedUniform> *uniforms) = 0;
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 4819ca0..6cb5c14 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -28,6 +28,36 @@
 namespace
 {
 
+GLenum GetTextureType(GLenum samplerType)
+{
+    switch (samplerType)
+    {
+      case GL_SAMPLER_2D:
+      case GL_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_SAMPLER_2D_SHADOW:
+        return GL_TEXTURE_2D;
+      case GL_SAMPLER_3D:
+      case GL_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+        return GL_TEXTURE_3D;
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_CUBE_SHADOW:
+        return GL_TEXTURE_CUBE_MAP;
+      case GL_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+        return GL_TEXTURE_CUBE_MAP;
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+        return GL_TEXTURE_2D_ARRAY;
+      default: UNREACHABLE();
+    }
+
+    return GL_TEXTURE_2D;
+}
+
 gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
 {
     gl::InputLayout defaultLayout;
@@ -308,6 +338,7 @@
       mUsedVertexSamplerRange(0),
       mUsedPixelSamplerRange(0),
       mDirtySamplerMapping(true),
+      mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits),
       mShaderVersion(100),
       mSerial(issueSerial())
 {
@@ -455,6 +486,106 @@
     }
 }
 
+bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
+{
+    // Skip cache if we're using an infolog, so we get the full error.
+    // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
+    if (!mDirtySamplerMapping && infoLog == nullptr && mCachedValidateSamplersResult.valid())
+    {
+        return mCachedValidateSamplersResult.value();
+    }
+
+    // if any two active samplers in a program are of different types, but refer to the same
+    // texture image unit, and this is the current program, then ValidateProgram will fail, and
+    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
+    updateSamplerMapping();
+
+    std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
+
+    for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
+    {
+        if (mSamplersPS[i].active)
+        {
+            unsigned int unit = mSamplersPS[i].logicalTextureUnit;
+
+            if (unit >= caps.maxCombinedTextureImageUnits)
+            {
+                if (infoLog)
+                {
+                    (*infoLog) << "Sampler uniform (" << unit
+                               << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
+                               << caps.maxCombinedTextureImageUnits << ")";
+                }
+
+                mCachedValidateSamplersResult = false;
+                return false;
+            }
+
+            if (mTextureUnitTypesCache[unit] != GL_NONE)
+            {
+                if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit])
+                {
+                    if (infoLog)
+                    {
+                        (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
+                                   << unit << ").";
+                    }
+
+                    mCachedValidateSamplersResult = false;
+                    return false;
+                }
+            }
+            else
+            {
+                mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType;
+            }
+        }
+    }
+
+    for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
+    {
+        if (mSamplersVS[i].active)
+        {
+            unsigned int unit = mSamplersVS[i].logicalTextureUnit;
+
+            if (unit >= caps.maxCombinedTextureImageUnits)
+            {
+                if (infoLog)
+                {
+                    (*infoLog) << "Sampler uniform (" << unit
+                               << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
+                               << caps.maxCombinedTextureImageUnits << ")";
+                }
+
+                mCachedValidateSamplersResult = false;
+                return false;
+            }
+
+            if (mTextureUnitTypesCache[unit] != GL_NONE)
+            {
+                if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit])
+                {
+                    if (infoLog)
+                    {
+                        (*infoLog) << "Samplers of conflicting types refer to the same texture image unit ("
+                                   << unit << ").";
+                    }
+
+                    mCachedValidateSamplersResult = false;
+                    return false;
+                }
+            }
+            else
+            {
+                mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType;
+            }
+        }
+    }
+
+    mCachedValidateSamplersResult = true;
+    return true;
+}
+
 LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
 {
     reset();
@@ -1042,7 +1173,7 @@
 
     initSemanticIndex();
 
-    defineUniformsAndAssignRegisters();
+    assignUniformRegisters();
 
     gatherTransformFeedbackVaryings(linkedVaryings);
 
@@ -1056,10 +1187,10 @@
     return LinkResult(true, gl::Error(GL_NO_ERROR));
 }
 
-GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
+GLboolean ProgramD3D::validate(const gl::Caps &caps, gl::InfoLog *infoLog)
 {
-    // TODO(jmadill): Do something useful here?
-    return GL_TRUE;
+    applyUniforms();
+    return validateSamplers(infoLog, caps);
 }
 
 void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
@@ -1344,19 +1475,17 @@
     setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
 }
 
-void ProgramD3D::defineUniformsAndAssignRegisters()
+void ProgramD3D::assignUniformRegisters()
 {
     const gl::Shader *vertexShader   = mData.getAttachedVertexShader();
     const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
 
-    D3DUniformMap uniformMap;
-
     for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
 
     {
         if (vertexUniform.staticUse)
         {
-            defineUniformBase(vertexShaderD3D, vertexUniform, &uniformMap);
+            assignUniformRegistersBase(vertexShaderD3D, vertexUniform);
         }
     }
 
@@ -1367,32 +1496,19 @@
     {
         if (fragmentUniform.staticUse)
         {
-            defineUniformBase(fragmentShaderD3D, fragmentUniform, &uniformMap);
+            assignUniformRegistersBase(fragmentShaderD3D, fragmentUniform);
         }
     }
 
-    // Initialize the D3DUniform list to mirror the indexing of the GL layer.
-    for (const gl::LinkedUniform &glUniform : mData.getUniforms())
-    {
-        if (!glUniform.isInDefaultBlock())
-            continue;
-
-        auto mapEntry = uniformMap.find(glUniform.name);
-        ASSERT(mapEntry != uniformMap.end());
-        mD3DUniforms.push_back(mapEntry->second);
-    }
-
     assignAllSamplerRegisters();
     initializeUniformStorage();
 }
 
-void ProgramD3D::defineUniformBase(const ShaderD3D *shader,
-                                   const sh::Uniform &uniform,
-                                   D3DUniformMap *uniformMap)
+void ProgramD3D::assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform)
 {
     if (uniform.isBuiltIn())
     {
-        defineUniform(shader, uniform, uniform.name, nullptr, uniformMap);
+        assignUniformRegisters(shader, uniform, uniform.name, nullptr);
         return;
     }
 
@@ -1401,7 +1517,7 @@
     sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
     encoder.skipRegisters(startRegister);
 
-    defineUniform(shader, uniform, uniform.name, &encoder, uniformMap);
+    assignUniformRegisters(shader, uniform, uniform.name, &encoder);
 }
 
 D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
@@ -1417,11 +1533,10 @@
     return nullptr;
 }
 
-void ProgramD3D::defineUniform(const ShaderD3D *shader,
-                               const sh::ShaderVariable &uniform,
-                               const std::string &fullName,
-                               sh::HLSLBlockEncoder *encoder,
-                               D3DUniformMap *uniformMap)
+void ProgramD3D::assignUniformRegisters(const ShaderD3D *shader,
+                                        const sh::ShaderVariable &uniform,
+                                        const std::string &fullName,
+                                        sh::HLSLBlockEncoder *encoder)
 {
     if (uniform.isStruct())
     {
@@ -1437,7 +1552,7 @@
                 const sh::ShaderVariable &field = uniform.fields[fieldIndex];
                 const std::string &fieldFullName = (fullName + elementString + "." + field.name);
 
-                defineUniform(shader, field, fieldFullName, encoder, uniformMap);
+                assignUniformRegisters(shader, field, fieldFullName, encoder);
             }
 
             if (encoder)
@@ -1457,23 +1572,27 @@
         encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
                 : sh::BlockMemberInfo::getDefaultBlockInfo();
 
-    auto uniformMapEntry   = uniformMap->find(fullName);
-    D3DUniform *d3dUniform = nullptr;
+    D3DUniform *d3dUniform = getD3DUniformByName(fullName);
 
-    if (uniformMapEntry != uniformMap->end())
+    if (!d3dUniform)
     {
-        d3dUniform = uniformMapEntry->second;
-    }
-    else
-    {
+        // We're building the list twice, make sure we use the same indexing. Special case
+        // built-ins.
+        ASSERT(fullName.compare(0, 3, "gl_") == 0 ||
+               mData.getUniformIndex(fullName) == static_cast<GLint>(mD3DUniforms.size()));
+
         d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
-        (*uniformMap)[fullName] = d3dUniform;
+        mD3DUniforms.push_back(d3dUniform);
+
+        if (encoder)
+        {
+            d3dUniform->registerElement =
+                static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
+        }
     }
 
     if (encoder)
     {
-        d3dUniform->registerElement =
-            static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo));
         unsigned int reg =
             static_cast<unsigned int>(sh::HLSLBlockEncoder::getBlockRegister(blockInfo));
         if (shader->getShaderType() == GL_FRAGMENT_SHADER)
@@ -1752,7 +1871,7 @@
         ASSERT(samplerIndex < outSamplers.size());
         Sampler *sampler            = &outSamplers[samplerIndex];
         sampler->active             = true;
-        sampler->textureType        = gl::SamplerTypeToTextureType(samplerType);
+        sampler->textureType        = GetTextureType(samplerType);
         sampler->logicalTextureUnit = 0;
         *outUsedRange               = std::max(samplerIndex + 1, *outUsedRange);
         samplerIndex++;
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h
index 2183961..5e86516 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "common/Optional.h"
 #include "compiler/translator/blocklayoutHLSL.h"
 #include "libANGLE/Constants.h"
 #include "libANGLE/formatutils.h"
@@ -32,7 +33,7 @@
 #endif
 
 // Helper struct representing a single shader uniform
-struct D3DUniform : angle::NonCopyable
+struct D3DUniform
 {
     D3DUniform(GLenum typeIn,
                const std::string &nameIn,
@@ -83,6 +84,7 @@
     GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
     GLint getUsedSamplerRange(gl::SamplerType type) const;
     void updateSamplerMapping();
+    bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps);
 
     bool usesPointSize() const { return mUsesPointSize; }
     bool usesPointSpriteEmulation() const;
@@ -196,18 +198,14 @@
         GLenum textureType;
     };
 
-    typedef std::map<std::string, D3DUniform *> D3DUniformMap;
     typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
 
-    void defineUniformsAndAssignRegisters();
-    void defineUniformBase(const ShaderD3D *shader,
-                           const sh::Uniform &uniform,
-                           D3DUniformMap *uniformMap);
-    void defineUniform(const ShaderD3D *shader,
-                       const sh::ShaderVariable &uniform,
-                       const std::string &fullName,
-                       sh::HLSLBlockEncoder *encoder,
-                       D3DUniformMap *uniformMap);
+    void assignUniformRegisters();
+    void assignUniformRegistersBase(const ShaderD3D *shader, const sh::Uniform &uniform);
+    void assignUniformRegisters(const ShaderD3D *shader,
+                                const sh::ShaderVariable &uniform,
+                                const std::string &fullName,
+                                sh::HLSLBlockEncoder *encoder);
     void assignAllSamplerRegisters();
     void assignSamplerRegisters(const D3DUniform *d3dUniform);
 
@@ -264,6 +262,9 @@
     GLuint mUsedPixelSamplerRange;
     bool mDirtySamplerMapping;
 
+    // Cache for validateSamplers
+    std::vector<GLenum> mTextureUnitTypesCache;
+
     // Cache for getPixelExecutableForFramebuffer
     std::vector<GLenum> mPixelShaderOutputFormatCache;
 
@@ -274,6 +275,8 @@
 
     unsigned int mSerial;
 
+    Optional<bool> mCachedValidateSamplersResult;
+
     std::vector<GLint> mVertexUBOCache;
     std::vector<GLint> mFragmentUBOCache;
     VertexExecutable::Signature mCachedVertexSignature;
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index bbb4540..bae8389 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -299,6 +299,12 @@
     mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
 }
 
+bool ProgramGL::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
+{
+    //UNIMPLEMENTED();
+    return true;
+}
+
 void ProgramGL::reset()
 {
     mUniformRealLocationMap.clear();
diff --git a/src/libANGLE/renderer/gl/ProgramGL.h b/src/libANGLE/renderer/gl/ProgramGL.h
index 982d5bb..9cc0a14 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/src/libANGLE/renderer/gl/ProgramGL.h
@@ -62,6 +62,8 @@
     void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
     void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
 
+    bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) override;
+
     void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
                                 std::vector<gl::LinkedUniform> *uniforms) override;
 
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index acb511f..e9f871d 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -703,366 +703,8 @@
     ASSERT_GL_NO_ERROR();
 }
 
-class TextureLimitsTest : public ANGLETest
-{
-  protected:
-    struct RGBA8
-    {
-        uint8_t R, G, B, A;
-    };
-
-    TextureLimitsTest()
-        : mProgram(0), mMaxVertexTextures(0), mMaxFragmentTextures(0), mMaxCombinedTextures(0)
-    {
-        setWindowWidth(128);
-        setWindowHeight(128);
-        setConfigRedBits(8);
-        setConfigGreenBits(8);
-        setConfigBlueBits(8);
-        setConfigAlphaBits(8);
-    }
-
-    ~TextureLimitsTest()
-    {
-        if (mProgram != 0)
-        {
-            glDeleteProgram(mProgram);
-            mProgram = 0;
-
-            if (!mTextures.empty())
-            {
-                glDeleteTextures(static_cast<GLsizei>(mTextures.size()), &mTextures[0]);
-            }
-        }
-    }
-
-    void SetUp() override
-    {
-        ANGLETest::SetUp();
-
-        glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mMaxVertexTextures);
-        glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mMaxFragmentTextures);
-        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxCombinedTextures);
-
-        ASSERT_GL_NO_ERROR();
-    }
-
-    void compileProgramWithTextureCounts(const std::string &vertexPrefix,
-                                         GLint vertexTextureCount,
-                                         GLint vertexActiveTextureCount,
-                                         const std::string &fragPrefix,
-                                         GLint fragmentTextureCount,
-                                         GLint fragmentActiveTextureCount)
-    {
-        std::stringstream vertexShaderStr;
-        vertexShaderStr << "attribute vec2 position;\n"
-                        << "varying vec4 color;\n"
-                        << "varying vec2 texCoord;\n";
-
-        for (GLint textureIndex = 0; textureIndex < vertexTextureCount; ++textureIndex)
-        {
-            vertexShaderStr << "uniform sampler2D " << vertexPrefix << textureIndex << ";\n";
-        }
-
-        vertexShaderStr << "void main() {\n"
-                        << "  gl_Position = vec4(position, 0, 1);\n"
-                        << "  texCoord = (position * 0.5) + 0.5;\n"
-                        << "  color = vec4(0);\n";
-
-        for (GLint textureIndex = 0; textureIndex < vertexActiveTextureCount; ++textureIndex)
-        {
-            vertexShaderStr << "  color += texture2D(" << vertexPrefix << textureIndex
-                            << ", texCoord);\n";
-        }
-
-        vertexShaderStr << "}";
-
-        std::stringstream fragmentShaderStr;
-        fragmentShaderStr << "varying mediump vec4 color;\n"
-                          << "varying mediump vec2 texCoord;\n";
-
-        for (GLint textureIndex = 0; textureIndex < fragmentTextureCount; ++textureIndex)
-        {
-            fragmentShaderStr << "uniform sampler2D " << fragPrefix << textureIndex << ";\n";
-        }
-
-        fragmentShaderStr << "void main() {\n"
-                          << "  gl_FragColor = color;\n";
-
-        for (GLint textureIndex = 0; textureIndex < fragmentActiveTextureCount; ++textureIndex)
-        {
-            fragmentShaderStr << "  gl_FragColor += texture2D(" << fragPrefix << textureIndex
-                              << ", texCoord);\n";
-        }
-
-        fragmentShaderStr << "}";
-
-        const std::string &vertexShaderSource   = vertexShaderStr.str();
-        const std::string &fragmentShaderSource = fragmentShaderStr.str();
-
-        mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
-    }
-
-    RGBA8 getPixel(GLint texIndex)
-    {
-        RGBA8 pixel = {static_cast<uint8_t>(texIndex & 0x7u), static_cast<uint8_t>(texIndex >> 3),
-                       0, 255u};
-        return pixel;
-    }
-
-    void initTextures(GLint tex2DCount, GLint texCubeCount)
-    {
-        GLint totalCount = tex2DCount + texCubeCount;
-        mTextures.assign(totalCount, 0);
-        glGenTextures(totalCount, &mTextures[0]);
-        ASSERT_GL_NO_ERROR();
-
-        std::vector<RGBA8> texData(16 * 16);
-
-        GLint texIndex = 0;
-        for (; texIndex < tex2DCount; ++texIndex)
-        {
-            texData.assign(texData.size(), getPixel(texIndex));
-            glActiveTexture(GL_TEXTURE0 + texIndex);
-            glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]);
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-                         &texData[0]);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        }
-
-        ASSERT_GL_NO_ERROR();
-
-        for (; texIndex < texCubeCount; ++texIndex)
-        {
-            texData.assign(texData.size(), getPixel(texIndex));
-            glActiveTexture(GL_TEXTURE0 + texIndex);
-            glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[texIndex]);
-            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
-                         GL_UNSIGNED_BYTE, &texData[0]);
-            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
-                         GL_UNSIGNED_BYTE, &texData[0]);
-            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
-                         GL_UNSIGNED_BYTE, &texData[0]);
-            glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
-                         GL_UNSIGNED_BYTE, &texData[0]);
-            glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
-                         GL_UNSIGNED_BYTE, &texData[0]);
-            glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
-                         GL_UNSIGNED_BYTE, &texData[0]);
-            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-            glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        }
-
-        ASSERT_GL_NO_ERROR();
-    }
-
-    void testWithTextures(GLint vertexTextureCount,
-                          const std::string &vertexTexturePrefix,
-                          GLint fragmentTextureCount,
-                          const std::string &fragmentTexturePrefix)
-    {
-        // Generate textures
-        initTextures(vertexTextureCount + fragmentTextureCount, 0);
-
-        glUseProgram(mProgram);
-        RGBA8 expectedSum = {0};
-        for (GLint texIndex = 0; texIndex < vertexTextureCount; ++texIndex)
-        {
-            std::stringstream uniformNameStr;
-            uniformNameStr << vertexTexturePrefix << texIndex;
-            const std::string &uniformName = uniformNameStr.str();
-            GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
-            ASSERT_NE(-1, location);
-
-            glUniform1i(location, texIndex);
-            RGBA8 contribution = getPixel(texIndex);
-            expectedSum.R += contribution.R;
-            expectedSum.G += contribution.G;
-        }
-
-        for (GLint texIndex = 0; texIndex < fragmentTextureCount; ++texIndex)
-        {
-            std::stringstream uniformNameStr;
-            uniformNameStr << fragmentTexturePrefix << texIndex;
-            const std::string &uniformName = uniformNameStr.str();
-            GLint location = glGetUniformLocation(mProgram, uniformName.c_str());
-            ASSERT_NE(-1, location);
-
-            glUniform1i(location, texIndex + vertexTextureCount);
-            RGBA8 contribution = getPixel(texIndex + vertexTextureCount);
-            expectedSum.R += contribution.R;
-            expectedSum.G += contribution.G;
-        }
-
-        ASSERT_GE(256u, expectedSum.G);
-
-        drawQuad(mProgram, "position", 0.5f);
-        ASSERT_GL_NO_ERROR();
-        EXPECT_PIXEL_EQ(0, 0, expectedSum.R, expectedSum.G, 0, 255);
-    }
-
-    GLuint mProgram;
-    std::vector<GLuint> mTextures;
-    GLint mMaxVertexTextures;
-    GLint mMaxFragmentTextures;
-    GLint mMaxCombinedTextures;
-};
-
-// Test rendering with the maximum vertex texture units.
-TEST_P(TextureLimitsTest, MaxVertexTextures)
-{
-    compileProgramWithTextureCounts("tex", mMaxVertexTextures, mMaxVertexTextures, "tex", 0, 0);
-    ASSERT_NE(0u, mProgram);
-    ASSERT_GL_NO_ERROR();
-
-    testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
-}
-
-// Test rendering with the maximum fragment texture units.
-TEST_P(TextureLimitsTest, MaxFragmentTextures)
-{
-    compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures, mMaxFragmentTextures);
-    ASSERT_NE(0u, mProgram);
-    ASSERT_GL_NO_ERROR();
-
-    testWithTextures(mMaxFragmentTextures, "tex", 0, "tex");
-}
-
-// Test rendering with maximum combined texture units.
-TEST_P(TextureLimitsTest, MaxCombinedTextures)
-{
-    GLint vertexTextures = mMaxVertexTextures;
-
-    if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
-    {
-        vertexTextures = mMaxCombinedTextures - mMaxFragmentTextures;
-    }
-
-    compileProgramWithTextureCounts("vtex", vertexTextures, vertexTextures, "ftex",
-                                    mMaxFragmentTextures, mMaxFragmentTextures);
-    ASSERT_NE(0u, mProgram);
-    ASSERT_GL_NO_ERROR();
-
-    testWithTextures(vertexTextures, "vtex", mMaxFragmentTextures, "ftex");
-}
-
-// Negative test for exceeding the number of vertex textures
-TEST_P(TextureLimitsTest, ExcessiveVertexTextures)
-{
-    compileProgramWithTextureCounts("tex", mMaxVertexTextures + 1, mMaxVertexTextures + 1, "tex", 0,
-                                    0);
-    ASSERT_EQ(0u, mProgram);
-}
-
-// Negative test for exceeding the number of fragment textures
-TEST_P(TextureLimitsTest, ExcessiveFragmentTextures)
-{
-    compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 1,
-                                    mMaxFragmentTextures + 1);
-    ASSERT_EQ(0u, mProgram);
-}
-
-// Test active vertex textures under the limit, but excessive textures specified.
-TEST_P(TextureLimitsTest, MaxActiveVertexTextures)
-{
-    compileProgramWithTextureCounts("tex", mMaxVertexTextures + 4, mMaxVertexTextures, "tex", 0, 0);
-    ASSERT_NE(0u, mProgram);
-    ASSERT_GL_NO_ERROR();
-
-    testWithTextures(mMaxVertexTextures, "tex", 0, "tex");
-}
-
-// Test active fragment textures under the limit, but excessive textures specified.
-TEST_P(TextureLimitsTest, MaxActiveFragmentTextures)
-{
-    compileProgramWithTextureCounts("tex", 0, 0, "tex", mMaxFragmentTextures + 4,
-                                    mMaxFragmentTextures);
-    ASSERT_NE(0u, mProgram);
-    ASSERT_GL_NO_ERROR();
-
-    testWithTextures(0, "tex", mMaxFragmentTextures, "tex");
-}
-
-// Negative test for pointing two sampler uniforms of different types to the same texture.
-TEST_P(TextureLimitsTest, TextureTypeConflict)
-{
-    const std::string &vertexShader =
-        "attribute vec2 position;\n"
-        "varying float color;\n"
-        "uniform sampler2D tex2D;\n"
-        "uniform samplerCube texCube;\n"
-        "void main() {\n"
-        "  gl_Position = vec4(position, 0, 1);\n"
-        "  vec2 texCoord = (position * 0.5) + 0.5;\n"
-        "  color = texture2D(tex2D, texCoord).x;\n"
-        "  color += textureCube(texCube, vec3(texCoord, 0)).x;\n"
-        "}";
-    const std::string &fragmentShader =
-        "varying mediump float color;\n"
-        "void main() {\n"
-        "  gl_FragColor = vec4(color, 0, 0, 1);\n"
-        "}";
-
-    mProgram = CompileProgram(vertexShader, fragmentShader);
-    ASSERT_NE(0u, mProgram);
-
-    initTextures(1, 0);
-
-    glUseProgram(mProgram);
-    GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
-    ASSERT_NE(-1, tex2DLocation);
-    GLint texCubeLocation = glGetUniformLocation(mProgram, "texCube");
-    ASSERT_NE(-1, texCubeLocation);
-
-    glUniform1i(tex2DLocation, 0);
-    glUniform1i(texCubeLocation, 0);
-    ASSERT_GL_NO_ERROR();
-
-    drawQuad(mProgram, "position", 0.5f);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-}
-
-// Negative test for rendering with texture outside the valid range.
-// TODO(jmadill): Research if this is correct.
-TEST_P(TextureLimitsTest, DrawWithTexturePastMaximum)
-{
-    const std::string &vertexShader =
-        "attribute vec2 position;\n"
-        "varying float color;\n"
-        "uniform sampler2D tex2D;\n"
-        "void main() {\n"
-        "  gl_Position = vec4(position, 0, 1);\n"
-        "  vec2 texCoord = (position * 0.5) + 0.5;\n"
-        "  color = texture2D(tex2D, texCoord).x;\n"
-        "}";
-    const std::string &fragmentShader =
-        "varying mediump float color;\n"
-        "void main() {\n"
-        "  gl_FragColor = vec4(color, 0, 0, 1);\n"
-        "}";
-
-    mProgram = CompileProgram(vertexShader, fragmentShader);
-    ASSERT_NE(0u, mProgram);
-
-    glUseProgram(mProgram);
-    GLint tex2DLocation = glGetUniformLocation(mProgram, "tex2D");
-    ASSERT_NE(-1, tex2DLocation);
-
-    glUniform1i(tex2DLocation, mMaxCombinedTextures);
-    ASSERT_GL_NO_ERROR();
-
-    drawQuad(mProgram, "position", 0.5f);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-}
-
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(TextureTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3()); // TODO(geofflang): Figure out why this test fails on Intel OpenGL
 ANGLE_INSTANTIATE_TEST(TextureTestES3, ES3_D3D11(), ES3_OPENGL());
-ANGLE_INSTANTIATE_TEST(TextureLimitsTest, ES2_D3D11(), ES2_OPENGL());
 
 } // namespace
diff --git a/src/tests/gl_tests/UniformTest.cpp b/src/tests/gl_tests/UniformTest.cpp
index 0cd3684..e1db43f 100644
--- a/src/tests/gl_tests/UniformTest.cpp
+++ b/src/tests/gl_tests/UniformTest.cpp
@@ -452,46 +452,6 @@
     }
 }
 
-// Check that sampler uniforms only show up one time in the list
-TEST_P(UniformTest, SamplerUniformsAppearOnce)
-{
-    const std::string &vertShader =
-        "attribute vec2 position;\n"
-        "uniform sampler2D tex2D;\n"
-        "varying vec4 color;\n"
-        "void main() {\n"
-        "  gl_Position = vec4(position, 0, 1);\n"
-        "  color = texture2D(tex2D, vec2(0));\n"
-        "}";
-
-    const std::string &fragShader =
-        "precision mediump float;\n"
-        "varying vec4 color;\n"
-        "uniform sampler2D tex2D;\n"
-        "void main() {\n"
-        "  gl_FragColor = texture2D(tex2D, vec2(0)) + color;\n"
-        "}";
-
-    GLuint program = CompileProgram(vertShader, fragShader);
-    ASSERT_NE(0u, program);
-
-    GLint activeUniformsCount = 0;
-    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniformsCount);
-    ASSERT_EQ(1, activeUniformsCount);
-
-    GLint size       = 0;
-    GLenum type      = GL_NONE;
-    GLchar name[120] = {0};
-    glGetActiveUniform(program, 0, 100, nullptr, &size, &type, name);
-    EXPECT_EQ(1, size);
-    EXPECT_EQ(GL_SAMPLER_2D, type);
-    EXPECT_STREQ("tex2D", name);
-
-    EXPECT_GL_NO_ERROR();
-
-    glDeleteProgram(program);
-}
-
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(UniformTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
 ANGLE_INSTANTIATE_TEST(UniformTestES3, ES3_D3D11(), ES3_OPENGL());