Optimize several functions for the Program perf test.

This gives the same or slightly better performance in the ProgramDraw
perf test. Also only set the Program object as dirty when there are
dirty bits set in the Program itself.

Bug: angleproject:2877
Change-Id: I07b428b40d3e3c24e0a42c970524756b6dc3a30e
Reviewed-on: https://chromium-review.googlesource.com/c/1271475
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index ee7ab9d..bafb7fb 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -135,10 +135,10 @@
     }
 }
 
-void MarkTransformFeedbackBufferUsage(const gl::Context *context,
-                                      gl::TransformFeedback *transformFeedback,
-                                      GLsizei count,
-                                      GLsizei instanceCount)
+ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const gl::Context *context,
+                                                   gl::TransformFeedback *transformFeedback,
+                                                   GLsizei count,
+                                                   GLsizei instanceCount)
 {
     if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
     {
@@ -6428,6 +6428,7 @@
     Program *programObject = getProgramResolveLink(program);
     programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
 
+    // Note: If the Program is shared between Contexts we would be better using Observer/Subject.
     if (programObject->isInUse())
     {
         mGLState.setObjectDirty(GL_PROGRAM);
@@ -7812,16 +7813,6 @@
     return false;
 }
 
-Program *Context::getProgramResolveLink(GLuint handle) const
-{
-    Program *program = mState.mShaderPrograms->getProgram(handle);
-    if (program)
-    {
-        program->resolveLink(this);
-    }
-    return program;
-}
-
 Program *Context::getProgramNoResolveLink(GLuint handle) const
 {
     return mState.mShaderPrograms->getProgram(handle);
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 140c3b7..aa5307e 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -1650,7 +1650,16 @@
     bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
     bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
 
-    Program *getProgramResolveLink(GLuint handle) const;
+    ANGLE_INLINE Program *getProgramResolveLink(GLuint handle) const
+    {
+        Program *program = mState.mShaderPrograms->getProgram(handle);
+        if (program)
+        {
+            program->resolveLink(this);
+        }
+        return program;
+    }
+
     Program *getProgramNoResolveLink(GLuint handle) const;
     Shader *getShader(GLuint handle) const;
 
diff --git a/src/libANGLE/Observer.cpp b/src/libANGLE/Observer.cpp
index 77c7ee0..b74abd6 100644
--- a/src/libANGLE/Observer.cpp
+++ b/src/libANGLE/Observer.cpp
@@ -118,11 +118,6 @@
     }
 }
 
-void ObserverBinding::reset()
-{
-    bind(nullptr);
-}
-
 void ObserverBinding::onStateChange(const gl::Context *context, SubjectMessage message) const
 {
     mObserver->onSubjectStateChange(context, mIndex, message);
diff --git a/src/libANGLE/Observer.h b/src/libANGLE/Observer.h
index f98c767..3c0ab8c 100644
--- a/src/libANGLE/Observer.h
+++ b/src/libANGLE/Observer.h
@@ -81,7 +81,9 @@
     ObserverBinding &operator=(const ObserverBinding &other);
 
     void bind(Subject *subject);
-    void reset();
+
+    ANGLE_INLINE void reset() { bind(nullptr); }
+
     void onStateChange(const gl::Context *context, SubjectMessage message) const;
     void onSubjectReset();
 
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index c0fd27c..dceb002 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -955,11 +955,6 @@
     ASSERT(mLinkResolved);
     return mState.mLabel;
 }
-rx::ProgramImpl *Program::getImplementation() const
-{
-    ASSERT(mLinkResolved);
-    return mProgram;
-}
 
 void Program::attachShader(Shader *shader)
 {
@@ -1567,21 +1562,10 @@
     return mState.mSeparable;
 }
 
-void Program::release(const Context *context)
+void Program::deleteSelf(const Context *context)
 {
-    ASSERT(mLinkResolved);
-    mRefCount--;
-
-    if (mRefCount == 0 && mDeleteStatus)
-    {
-        mResourceManager->deleteProgram(context, mHandle);
-    }
-}
-
-void Program::addRef()
-{
-    ASSERT(mLinkResolved);
-    mRefCount++;
+    ASSERT(mRefCount == 0 && mDeleteStatus);
+    mResourceManager->deleteProgram(context, mHandle);
 }
 
 unsigned int Program::getRefCount() const
@@ -2375,18 +2359,6 @@
     return mValidated;
 }
 
-GLuint Program::getActiveAtomicCounterBufferCount() const
-{
-    ASSERT(mLinkResolved);
-    return static_cast<GLuint>(mState.mAtomicCounterBuffers.size());
-}
-
-GLuint Program::getActiveShaderStorageBlockCount() const
-{
-    ASSERT(mLinkResolved);
-    return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
-}
-
 void Program::getActiveUniformBlockName(const GLuint blockIndex,
                                         GLsizei bufSize,
                                         GLsizei *length,
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index fbf14c5..29f87a8 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -497,7 +497,11 @@
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
 
-    rx::ProgramImpl *getImplementation() const;
+    ANGLE_INLINE rx::ProgramImpl *getImplementation() const
+    {
+        ASSERT(mLinkResolved);
+        return mProgram;
+    }
 
     void attachShader(Shader *shader);
     void detachShader(const Context *context, Shader *shader);
@@ -675,13 +679,25 @@
                                          GLsizei bufSize,
                                          GLsizei *length,
                                          GLchar *blockName) const;
-    GLuint getActiveUniformBlockCount() const
+
+    ANGLE_INLINE GLuint getActiveUniformBlockCount() const
     {
+        ASSERT(mLinkResolved);
         return static_cast<GLuint>(mState.mUniformBlocks.size());
     }
 
-    GLuint getActiveAtomicCounterBufferCount() const;
-    GLuint getActiveShaderStorageBlockCount() const;
+    ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
+    {
+        ASSERT(mLinkResolved);
+        return static_cast<GLuint>(mState.mAtomicCounterBuffers.size());
+    }
+
+    ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
+    {
+        ASSERT(mLinkResolved);
+        return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
+    }
+
     GLint getActiveUniformBlockMaxNameLength() const;
     GLint getActiveShaderStorageBlockMaxNameLength() const;
 
@@ -710,8 +726,23 @@
     GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
     const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
 
-    void addRef();
-    void release(const Context *context);
+    ANGLE_INLINE void addRef()
+    {
+        ASSERT(mLinkResolved);
+        mRefCount++;
+    }
+
+    ANGLE_INLINE void release(const Context *context)
+    {
+        ASSERT(mLinkResolved);
+        mRefCount--;
+
+        if (mRefCount == 0 && mDeleteStatus)
+        {
+            deleteSelf(context);
+        }
+    }
+
     unsigned int getRefCount() const;
     bool isInUse() const { return getRefCount() != 0; }
     void flagForDeletion();
@@ -820,12 +851,15 @@
         }
     }
 
+    ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
   private:
     struct LinkingState;
 
     ~Program() override;
 
     void unlink();
+    void deleteSelf(const Context *context);
 
     bool linkValidateShaders(InfoLog &infoLog);
     bool linkAttributes(const Caps &caps, InfoLog &infoLog);
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 63bf64c..b00d379 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -191,11 +191,6 @@
     deleteObject(context, &mPrograms, program);
 }
 
-Program *ShaderProgramManager::getProgram(GLuint handle) const
-{
-    return mPrograms.query(handle);
-}
-
 template <typename ObjectType>
 void ShaderProgramManager::deleteObject(const Context *context,
                                         ResourceMap<ObjectType> *objectMap,
diff --git a/src/libANGLE/ResourceManager.h b/src/libANGLE/ResourceManager.h
index 3ca900e..1420aef 100644
--- a/src/libANGLE/ResourceManager.h
+++ b/src/libANGLE/ResourceManager.h
@@ -147,7 +147,8 @@
 
     GLuint createProgram(rx::GLImplFactory *factory);
     void deleteProgram(const Context *context, GLuint program);
-    Program *getProgram(GLuint handle) const;
+
+    ANGLE_INLINE Program *getProgram(GLuint handle) const { return mPrograms.query(handle); }
 
   protected:
     ~ShaderProgramManager() override;
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index a6f8bea..0c29a3e 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -1423,13 +1423,6 @@
     mDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
 }
 
-bool State::isTransformFeedbackActiveUnpaused() const
-{
-    TransformFeedback *curTransformFeedback = mTransformFeedback.get();
-    return curTransformFeedback && curTransformFeedback->isActive() &&
-           !curTransformFeedback->isPaused();
-}
-
 bool State::removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback)
 {
     if (mTransformFeedback.id() == transformFeedback)
@@ -2913,7 +2906,11 @@
     ASSERT(program->isLinked());
 
     mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
-    mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+
+    if (program->hasAnyDirtyBit())
+    {
+        mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+    }
 
     // Set any bound textures.
     const ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
index 7394ee1..510ce2b 100644
--- a/src/libANGLE/State.h
+++ b/src/libANGLE/State.h
@@ -247,7 +247,13 @@
     void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
     TransformFeedback *getCurrentTransformFeedback() const { return mTransformFeedback.get(); }
 
-    bool isTransformFeedbackActiveUnpaused() const;
+    ANGLE_INLINE bool isTransformFeedbackActiveUnpaused() const
+    {
+        TransformFeedback *curTransformFeedback = mTransformFeedback.get();
+        return curTransformFeedback && curTransformFeedback->isActive() &&
+               !curTransformFeedback->isPaused();
+    }
+
     bool removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback);
 
     // Query binding manipulation
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 223e3ad..1e49893 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -658,11 +658,6 @@
     }
 }
 
-GLuint ProgramGL::getProgramID() const
-{
-    return mProgramID;
-}
-
 bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
                                     const std::string &blockMappedName,
                                     size_t *sizeOut) const
diff --git a/src/libANGLE/renderer/gl/ProgramGL.h b/src/libANGLE/renderer/gl/ProgramGL.h
index 7d814a4..d2e669c 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/src/libANGLE/renderer/gl/ProgramGL.h
@@ -78,7 +78,7 @@
                                     std::vector<gl::SamplerBinding> *samplerBindings,
                                     std::vector<gl::ImageBinding> *imageBindings) override;
 
-    GLuint getProgramID() const;
+    ANGLE_INLINE GLuint getProgramID() const { return mProgramID; }
 
     void enableSideBySideRenderingPath() const;
     void enableLayeredRenderingPath(int baseViewIndex) const;
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index d7b6956..3875349 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2122,19 +2122,6 @@
     return false;
 }
 
-bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
-{
-    // Check that the value type is compatible with uniform type.
-    // Do the cheaper test first, for a little extra speed.
-    if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
-    {
-        return true;
-    }
-
-    ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
-    return false;
-}
-
 bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
 {
     // Check that the value type is compatible with uniform type.
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index d15a4ec..28b0f6b 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -11,7 +11,9 @@
 
 #include "common/PackedEnums.h"
 #include "common/mathutil.h"
+#include "common/utilities.h"
 #include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
 #include "libANGLE/Framebuffer.h"
 
 #include <GLES2/gl2.h>
@@ -219,7 +221,19 @@
                              GLenum uniformType,
                              GLsizei count,
                              const GLint *value);
-bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType);
+
+ANGLE_INLINE bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
+{
+    // Check that the value type is compatible with uniform type.
+    // Do the cheaper test first, for a little extra speed.
+    if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType)
+    {
+        context->validationError(GL_INVALID_OPERATION, kErrorUniformSizeMismatch);
+        return false;
+    }
+    return true;
+}
+
 bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType);
 bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count);
 bool ValidateUniformMatrix(Context *context,