Defer shader compiles when possible.

When using the program binary memory cache inside ANGLE, this will
give a potential fast path. If the user doesn't query the shader
compile status or info log before calling LinkProgram, then we can
check the program cache before translating the program, and if it
finds a hit, we don't even need to call the translator.

To preserve the shader settings at compile time, a reference to the
current shader translator is kept in a binding pointer on the call
to compile. This mirrors a similar implementation in Chromium's
command buffer. Also the compile options and source are cached at
compile to preserve the correct shader state.

BUG=angleproject:1897

Change-Id: I3c046d7ac8c3b5c8cc169c4802ffe47f95537212
Reviewed-on: https://chromium-review.googlesource.com/517379
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/UniformLinker.cpp b/src/libANGLE/UniformLinker.cpp
index 8b735c4..f0ed125 100644
--- a/src/libANGLE/UniformLinker.cpp
+++ b/src/libANGLE/UniformLinker.cpp
@@ -12,6 +12,7 @@
 
 #include "common/utilities.h"
 #include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
 #include "libANGLE/Shader.h"
 #include "libANGLE/features.h"
 
@@ -45,14 +46,14 @@
     uniformLocations->swap(mUniformLocations);
 }
 
-bool UniformLinker::link(InfoLog &infoLog,
-                         const Caps &caps,
+bool UniformLinker::link(const Context *context,
+                         InfoLog &infoLog,
                          const Program::Bindings &uniformLocationBindings)
 {
     if (mState.getAttachedVertexShader() && mState.getAttachedFragmentShader())
     {
         ASSERT(mState.getAttachedComputeShader() == nullptr);
-        if (!validateVertexAndFragmentUniforms(infoLog))
+        if (!validateVertexAndFragmentUniforms(context, infoLog))
         {
             return false;
         }
@@ -60,7 +61,7 @@
 
     // 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))
+    if (!flattenUniformsAndCheckCaps(context, infoLog))
     {
         return false;
     }
@@ -73,14 +74,15 @@
     return true;
 }
 
-bool UniformLinker::validateVertexAndFragmentUniforms(InfoLog &infoLog) const
+bool UniformLinker::validateVertexAndFragmentUniforms(const Context *context,
+                                                      InfoLog &infoLog) const
 {
     // Check that uniforms defined in the vertex and fragment shaders are identical
     std::map<std::string, LinkedUniform> linkedUniforms;
     const std::vector<sh::Uniform> &vertexUniforms =
-        mState.getAttachedVertexShader()->getUniforms();
+        mState.getAttachedVertexShader()->getUniforms(context);
     const std::vector<sh::Uniform> &fragmentUniforms =
-        mState.getAttachedFragmentShader()->getUniforms();
+        mState.getAttachedFragmentShader()->getUniforms(context);
 
     for (const sh::Uniform &vertexUniform : vertexUniforms)
     {
@@ -319,7 +321,8 @@
 }
 
 bool UniformLinker::flattenUniformsAndCheckCapsForShader(
-    const Shader &shader,
+    const Context *context,
+    Shader *shader,
     GLuint maxUniformComponents,
     GLuint maxTextureImageUnits,
     const std::string &componentsErrorMessage,
@@ -328,7 +331,7 @@
     InfoLog &infoLog)
 {
     VectorAndSamplerCount vasCount;
-    for (const sh::Uniform &uniform : shader.getUniforms())
+    for (const sh::Uniform &uniform : shader->getUniforms(context))
     {
         vasCount += flattenUniform(uniform, &samplerUniforms);
     }
@@ -348,17 +351,19 @@
     return true;
 }
 
-bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
+bool UniformLinker::flattenUniformsAndCheckCaps(const Context *context, InfoLog &infoLog)
 {
     std::vector<LinkedUniform> samplerUniforms;
 
+    const Caps &caps = context->getCaps();
+
     if (mState.getAttachedComputeShader())
     {
-        const Shader *computeShader = mState.getAttachedComputeShader();
+        Shader *computeShader = mState.getAttachedComputeShader();
 
         // TODO (mradev): check whether we need finer-grained component counting
         if (!flattenUniformsAndCheckCapsForShader(
-                *computeShader, caps.maxComputeUniformComponents / 4,
+                context, computeShader, caps.maxComputeUniformComponents / 4,
                 caps.maxComputeTextureImageUnits,
                 "Compute shader active uniforms exceed MAX_COMPUTE_UNIFORM_COMPONENTS (",
                 "Compute shader sampler count exceeds MAX_COMPUTE_TEXTURE_IMAGE_UNITS (",
@@ -369,20 +374,22 @@
     }
     else
     {
-        const Shader *vertexShader = mState.getAttachedVertexShader();
+        Shader *vertexShader = mState.getAttachedVertexShader();
 
         if (!flattenUniformsAndCheckCapsForShader(
-                *vertexShader, caps.maxVertexUniformVectors, caps.maxVertexTextureImageUnits,
+                context, vertexShader, caps.maxVertexUniformVectors,
+                caps.maxVertexTextureImageUnits,
                 "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS (",
                 "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (",
                 samplerUniforms, infoLog))
         {
             return false;
         }
-        const Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+        Shader *fragmentShader = mState.getAttachedFragmentShader();
 
         if (!flattenUniformsAndCheckCapsForShader(
-                *fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits,
+                context, fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits,
                 "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS (",
                 "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (", samplerUniforms,
                 infoLog))