Optimize Texture initialization tracking with extra caching.

In both Texture and State, track when all images/textures are
initailized so that State::clearUnclearedActiveTextures can early-exit.

Improves performance on the WebGL Aquarium by 26% (23->29 FPS) with 30000
fish.

BUG=angleproject:2188

Change-Id: Ie2860a81d7be19ee87262325d8cf27bde43f80b8
Reviewed-on: https://chromium-review.googlesource.com/782339
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 1b33c68..f87e963 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -170,6 +170,7 @@
     }
     mCompleteTextureCache.resize(caps.maxCombinedTextureImageUnits, nullptr);
     mCompleteTextureBindings.reserve(caps.maxCombinedTextureImageUnits);
+    mCachedTexturesInitState = InitState::MayNeedInit;
     for (uint32_t textureIndex = 0; textureIndex < caps.maxCombinedTextureImageUnits;
          ++textureIndex)
     {
@@ -2234,6 +2235,10 @@
 
     ActiveTextureMask newActiveTextures;
 
+    // Initialize to the 'Initialized' state and set to 'MayNeedInit' if any texture is not
+    // initialized.
+    mCachedTexturesInitState = InitState::Initialized;
+
     for (const SamplerBinding &samplerBinding : mProgram->getSamplerBindings())
     {
         if (samplerBinding.unreferenced)
@@ -2271,6 +2276,11 @@
             {
                 sampler->syncState(context);
             }
+
+            if (texture->initState() == InitState::MayNeedInit)
+            {
+                mCachedTexturesInitState = InitState::MayNeedInit;
+            }
         }
     }
 
@@ -2383,12 +2393,22 @@
     // Conservatively assume all textures are dirty.
     // TODO(jmadill): More fine-grained update.
     mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+
+    if (initState == InitState::MayNeedInit)
+    {
+        mCachedTexturesInitState = InitState::MayNeedInit;
+    }
 }
 
 Error State::clearUnclearedActiveTextures(const Context *context)
 {
     ASSERT(mRobustResourceInit);
 
+    if (mCachedTexturesInitState == InitState::Initialized)
+    {
+        return NoError();
+    }
+
     for (auto textureIndex : mActiveTexturesMask)
     {
         Texture *texture = mCompleteTextureCache[textureIndex];
@@ -2398,6 +2418,8 @@
         }
     }
 
+    mCachedTexturesInitState = InitState::Initialized;
+
     return NoError();
 }