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

This previously was D3D-only, but is required for every draw call.
This completes the work of removing the D3D-specific Impl methods
from ProgramImpl.

Also add several regression tests to cover texture and sampler
validation.

Re-land with a fix for duplicate sampler active uniforms.

BUG=angleproject:1123

Change-Id: Iefef06e7901873c98bf2ba7864efd16a4c6435d3
Reviewed-on: https://chromium-review.googlesource.com/301581
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 3dd7c46..6e9d682 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -10,13 +10,6 @@
 #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>
 
@@ -25,6 +18,15 @@
 #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;
@@ -215,6 +217,11 @@
         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;
@@ -384,7 +391,8 @@
     };
 
     VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
-                                         const std::string &fullName);
+                                         const std::string &fullName,
+                                         std::vector<LinkedUniform> *samplerUniforms);
 
     void gatherInterfaceBlockInfo();
     void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
@@ -414,6 +422,11 @@
     const GLuint mHandle;
 
     InfoLog mInfoLog;
+
+    // Cache for sampler validation
+    Optional<bool> mCachedValidateSamplersResult;
+    std::vector<GLenum> mTextureUnitTypesCache;
+    RangeUI mSamplerUniformRange;
 };
 }