Context: Cache VAO element limits.

Cache the minimum value for non instanced and instanced active
attributes. The cache is updated in the following places:

1. Context: bindVertexArray.
2. Context: any executable change (linkProgram/useProgram/programBinary).
3. Vertex Array: any state change call.
4. Buffer: a dependent buffer resize.

This greatly reduces the time we're spending in ValidateDrawAttribs.

Bug: angleproject:1391
Change-Id: I84bb222a1b9736e6165fe40e972cd4299ca1178d
Reviewed-on: https://chromium-review.googlesource.com/1150516
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index a014ac3..2650fbc 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -109,9 +109,6 @@
 
 bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
 {
-    const gl::State &state     = context->getGLState();
-    const gl::Program *program = state.getProgram();
-
     if (!ValidateDrawClientAttribs(context))
     {
         return false;
@@ -123,39 +120,24 @@
         return true;
     }
 
-    const VertexArray *vao     = state.getVertexArray();
-    const auto &vertexAttribs  = vao->getVertexAttributes();
-    const auto &vertexBindings = vao->getVertexBindings();
-
-    const AttributesMask &activeAttribs = context->getStateCache().getActiveBufferedAttribsMask();
-
-    for (size_t attributeIndex : activeAttribs)
+    if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
+        (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
     {
-        const VertexAttribute &attrib = vertexAttribs[attributeIndex];
-        ASSERT(attrib.enabled);
-
-        const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
-        ASSERT(context->isGLES1() || program->isAttribLocationActive(attributeIndex));
-
-        GLint maxVertexElement = binding.getDivisor() != 0 ? (primcount - 1) : maxVertex;
-
-        if (maxVertexElement > attrib.getCachedElementLimit())
-        {
-            // An overflow can happen when adding the offset. Negative indicates overflow.
-            if (attrib.getCachedElementLimit() < 0)
-            {
-                ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
-                return false;
-            }
-
-            // [OpenGL ES 3.0.2] section 2.9.4 page 40:
-            // We can return INVALID_OPERATION if our buffer does not have enough backing data.
-            ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
-            return false;
-        }
+        return true;
     }
 
-    return true;
+    // An overflow can happen when adding the offset. Negative indicates overflow.
+    if (context->getStateCache().getNonInstancedVertexElementLimit() < 0 ||
+        context->getStateCache().getInstancedVertexElementLimit() < 0)
+    {
+        ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+        return false;
+    }
+
+    // [OpenGL ES 3.0.2] section 2.9.4 page 40:
+    // We can return INVALID_OPERATION if our buffer does not have enough backing data.
+    ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
+    return false;
 }
 
 bool ValidReadPixelsTypeEnum(Context *context, GLenum type)