Optimize resolveLink.

This changes the program query to resolve the link if required. If the
validation layer is skipped the link is resolved in the gl::Context.
Resolving the link on program query allows us to avoid resolving the
link on most of the gl::Program query APIs.

This improves inlining and particularly affects uniform update. It
fixes a performance regression introduced by the parallel shader
linking extension. Gives a 17% increased score on a uniform benchmark.

Also fixes two missing cases of checking for the extension in our
validation code.

Note that some bugs might still exist when the validation layer is
disabled.

Bug: angleproject:2851
Change-Id: I5d725eede3fa147cedf2ce0129791b3412a97a61
Reviewed-on: https://chromium-review.googlesource.com/1255509
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@google.com>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 374e174..f1efed8 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -1024,7 +1024,7 @@
         case GL_SHADER:
             return getShader(name);
         case GL_PROGRAM:
-            return getProgram(name);
+            return getProgramNoResolveLink(name);
         case GL_VERTEX_ARRAY:
             return getVertexArray(name);
         case GL_QUERY:
@@ -1178,7 +1178,7 @@
 
 void Context::useProgram(GLuint program)
 {
-    mGLState.setProgram(this, getProgram(program));
+    mGLState.setProgram(this, getProgramResolveLink(program));
     mStateCache.onProgramExecutableChange(this);
 }
 
@@ -2340,7 +2340,7 @@
 
 void Context::bindUniformLocation(GLuint program, GLint location, const GLchar *name)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
 
     programObject->bindUniformLocation(location, name);
@@ -2538,7 +2538,7 @@
 
 void Context::bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name)
 {
-    auto *programObject = getProgram(program);
+    auto *programObject = getProgramResolveLink(program);
 
     programObject->bindFragmentInputLocation(location, name);
 }
@@ -2549,14 +2549,14 @@
                                           GLint components,
                                           const GLfloat *coeffs)
 {
-    auto *programObject = getProgram(program);
+    auto *programObject = getProgramResolveLink(program);
 
     programObject->pathFragmentInputGen(location, genMode, components, coeffs);
 }
 
 GLuint Context::getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name)
 {
-    const auto *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     return QueryProgramResourceIndex(programObject, programInterface, name);
 }
 
@@ -2567,7 +2567,7 @@
                                      GLsizei *length,
                                      GLchar *name)
 {
-    const auto *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     QueryProgramResourceName(programObject, programInterface, index, bufSize, length, name);
 }
 
@@ -2575,7 +2575,7 @@
                                           GLenum programInterface,
                                           const GLchar *name)
 {
-    const auto *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     return QueryProgramResourceLocation(programObject, programInterface, name);
 }
 
@@ -2588,7 +2588,7 @@
                                    GLsizei *length,
                                    GLint *params)
 {
-    const auto *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     QueryProgramResourceiv(programObject, programInterface, index, propCount, props, bufSize,
                            length, params);
 }
@@ -2598,7 +2598,7 @@
                                     GLenum pname,
                                     GLint *params)
 {
-    const auto *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     QueryProgramInterfaceiv(programObject, programInterface, pname, params);
 }
 
@@ -2960,7 +2960,7 @@
 
 void Context::programParameteri(GLuint program, GLenum pname, GLint value)
 {
-    gl::Program *programObject = getProgram(program);
+    gl::Program *programObject = getProgramResolveLink(program);
     SetProgramParameteri(programObject, pname, value);
 }
 
@@ -5018,8 +5018,8 @@
 
 void Context::bindAttribLocation(GLuint program, GLuint index, const GLchar *name)
 {
-    Program *programObject = getProgram(program);
-    // TODO(jmadill): Re-use this from the validation if possible.
+    // Ideally we could share the program query with the validation layer if possible.
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->bindAttributeLocation(index, name);
 }
@@ -5313,7 +5313,7 @@
 
 void Context::detachShader(GLuint program, GLuint shader)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramNoResolveLink(program);
     ASSERT(programObject);
 
     Shader *shaderObject = getShader(shader);
@@ -5362,7 +5362,7 @@
                               GLenum *type,
                               GLchar *name)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->getActiveAttribute(index, bufsize, length, size, type, name);
 }
@@ -5375,21 +5375,21 @@
                                GLenum *type,
                                GLchar *name)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->getActiveUniform(index, bufsize, length, size, type, name);
 }
 
 void Context::getAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramNoResolveLink(program);
     ASSERT(programObject);
     programObject->getAttachedShaders(maxcount, count, shaders);
 }
 
 GLint Context::getAttribLocation(GLuint program, const GLchar *name)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     return programObject->getAttributeLocation(name);
 }
@@ -5459,7 +5459,9 @@
 
 void Context::getProgramiv(GLuint program, GLenum pname, GLint *params)
 {
-    Program *programObject = getProgram(program);
+    // Don't resolve link if checking the link completion status.
+    Program *programObject = (pname == GL_COMPLETION_STATUS_KHR ? getProgramNoResolveLink(program)
+                                                                : getProgramResolveLink(program));
     ASSERT(programObject);
     QueryProgramiv(this, programObject, pname, params);
 }
@@ -5480,7 +5482,7 @@
 
 void Context::getProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->getInfoLog(bufsize, length, infolog);
 }
@@ -5598,7 +5600,7 @@
 
 void Context::getUniformfv(GLuint program, GLint location, GLfloat *params)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->getUniformfv(this, location, params);
 }
@@ -5614,7 +5616,7 @@
 
 void Context::getUniformiv(GLuint program, GLint location, GLint *params)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->getUniformiv(this, location, params);
 }
@@ -5630,7 +5632,7 @@
 
 GLint Context::getUniformLocation(GLuint program, const GLchar *name)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     return programObject->getUniformLocation(name);
 }
@@ -5667,7 +5669,7 @@
         return GL_FALSE;
     }
 
-    return (getProgram(program) ? GL_TRUE : GL_FALSE);
+    return (getProgramNoResolveLink(program) ? GL_TRUE : GL_FALSE);
 }
 
 GLboolean Context::isRenderbuffer(GLuint renderbuffer)
@@ -5702,7 +5704,7 @@
 
 void Context::linkProgram(GLuint program)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramNoResolveLink(program);
     ASSERT(programObject);
     handleError(programObject->link(this));
 
@@ -5715,6 +5717,7 @@
     //      ProgramD3D.
     if (programObject->isInUse())
     {
+        programObject->resolveLink();
         if (programObject->isLinked())
         {
             mGLState.onProgramExecutableChange(programObject);
@@ -5902,7 +5905,7 @@
 
 void Context::validateProgram(GLuint program)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->validate(mCaps);
 }
@@ -5918,7 +5921,7 @@
                                GLenum *binaryFormat,
                                void *binary)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject != nullptr);
 
     handleError(programObject->saveBinary(this, binaryFormat, binary, bufSize, length));
@@ -5926,7 +5929,7 @@
 
 void Context::programBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject != nullptr);
 
     handleError(programObject->loadBinary(this, binaryFormat, binary, length));
@@ -6130,7 +6133,7 @@
                                         const GLchar *const *varyings,
                                         GLenum bufferMode)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
 }
@@ -6143,7 +6146,7 @@
                                           GLenum *type,
                                           GLchar *name)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
 }
@@ -6209,7 +6212,7 @@
 
 void Context::getUniformuiv(GLuint program, GLint location, GLuint *params)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     programObject->getUniformuiv(this, location, params);
 }
 
@@ -6224,7 +6227,7 @@
 
 GLint Context::getFragDataLocation(GLuint program, const GLchar *name)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     return programObject->getFragDataLocation(name);
 }
 
@@ -6233,7 +6236,7 @@
                                 const GLchar *const *uniformNames,
                                 GLuint *uniformIndices)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     if (!programObject->isLinked())
     {
         for (int uniformId = 0; uniformId < uniformCount; uniformId++)
@@ -6256,7 +6259,7 @@
                                   GLenum pname,
                                   GLint *params)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     for (int uniformId = 0; uniformId < uniformCount; uniformId++)
     {
         const GLuint index = uniformIndices[uniformId];
@@ -6266,7 +6269,7 @@
 
 GLuint Context::getUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     return programObject->getUniformBlockIndex(uniformBlockName);
 }
 
@@ -6275,7 +6278,7 @@
                                       GLenum pname,
                                       GLint *params)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
 }
 
@@ -6295,7 +6298,7 @@
                                         GLsizei *length,
                                         GLchar *uniformBlockName)
 {
-    const Program *programObject = getProgram(program);
+    const Program *programObject = getProgramResolveLink(program);
     programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
 }
 
@@ -6303,7 +6306,7 @@
                                   GLuint uniformBlockIndex,
                                   GLuint uniformBlockBinding)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
 
     if (programObject->isInUse())
@@ -6515,84 +6518,84 @@
 
 void Context::programUniform1iv(GLuint program, GLint location, GLsizei count, const GLint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     setUniform1iImpl(programObject, location, count, value);
 }
 
 void Context::programUniform2iv(GLuint program, GLint location, GLsizei count, const GLint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform2iv(location, count, value);
 }
 
 void Context::programUniform3iv(GLuint program, GLint location, GLsizei count, const GLint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform3iv(location, count, value);
 }
 
 void Context::programUniform4iv(GLuint program, GLint location, GLsizei count, const GLint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform4iv(location, count, value);
 }
 
 void Context::programUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform1uiv(location, count, value);
 }
 
 void Context::programUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform2uiv(location, count, value);
 }
 
 void Context::programUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform3uiv(location, count, value);
 }
 
 void Context::programUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform4uiv(location, count, value);
 }
 
 void Context::programUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform1fv(location, count, value);
 }
 
 void Context::programUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform2fv(location, count, value);
 }
 
 void Context::programUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform3fv(location, count, value);
 }
 
 void Context::programUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniform4fv(location, count, value);
 }
@@ -6603,7 +6606,7 @@
                                       GLboolean transpose,
                                       const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix2fv(location, count, transpose, value);
 }
@@ -6614,7 +6617,7 @@
                                       GLboolean transpose,
                                       const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix3fv(location, count, transpose, value);
 }
@@ -6625,7 +6628,7 @@
                                       GLboolean transpose,
                                       const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix4fv(location, count, transpose, value);
 }
@@ -6636,7 +6639,7 @@
                                         GLboolean transpose,
                                         const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix2x3fv(location, count, transpose, value);
 }
@@ -6647,7 +6650,7 @@
                                         GLboolean transpose,
                                         const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix3x2fv(location, count, transpose, value);
 }
@@ -6658,7 +6661,7 @@
                                         GLboolean transpose,
                                         const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix2x4fv(location, count, transpose, value);
 }
@@ -6669,7 +6672,7 @@
                                         GLboolean transpose,
                                         const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix4x2fv(location, count, transpose, value);
 }
@@ -6680,7 +6683,7 @@
                                         GLboolean transpose,
                                         const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix3x4fv(location, count, transpose, value);
 }
@@ -6691,7 +6694,7 @@
                                         GLboolean transpose,
                                         const GLfloat *value)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
     programObject->setUniformMatrix4x3fv(location, count, transpose, value);
 }
@@ -6791,7 +6794,7 @@
 
 void Context::getnUniformfv(GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
 
     programObject->getUniformfv(this, location, params);
@@ -6808,7 +6811,7 @@
 
 void Context::getnUniformiv(GLuint program, GLint location, GLsizei bufSize, GLint *params)
 {
-    Program *programObject = getProgram(program);
+    Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
 
     programObject->getUniformiv(this, location, params);
@@ -7690,7 +7693,17 @@
     return false;
 }
 
-Program *Context::getProgram(GLuint handle) const
+Program *Context::getProgramResolveLink(GLuint handle) const
+{
+    Program *program = mState.mShaderPrograms->getProgram(handle);
+    if (program)
+    {
+        program->resolveLink();
+    }
+    return program;
+}
+
+Program *Context::getProgramNoResolveLink(GLuint handle) const
 {
     return mState.mShaderPrograms->getProgram(handle);
 }