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/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++;