Revert "Implement dirty bits acceleration for VertexArrayGL."

Seems to cause an exception in Release, in end2end_tests.

BUG=angleproject:1040

This reverts commit 6d51c70ccf63a2c5ec240d960ff1bc179d36c92c.

Change-Id: I6548bc68dce07d2d85e40afdb604157e689c1d6c
Reviewed-on: https://chromium-review.googlesource.com/293821
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index 0da7375..9e7cce8 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -8,7 +8,6 @@
 
 #include "libANGLE/renderer/gl/VertexArrayGL.h"
 
-#include "common/BitSetIterator.h"
 #include "common/debug.h"
 #include "common/mathutil.h"
 #include "common/utilities.h"
@@ -19,20 +18,10 @@
 #include "libANGLE/renderer/gl/FunctionsGL.h"
 #include "libANGLE/renderer/gl/StateManagerGL.h"
 
-using namespace gl;
-
 namespace rx
 {
-namespace
-{
-bool AttributeNeedsStreaming(const VertexAttribute &attribute)
-{
-    return (attribute.enabled && attribute.buffer.get() == nullptr);
-}
 
-}  // anonymous namespace
-
-VertexArrayGL::VertexArrayGL(const VertexArray::Data &data,
+VertexArrayGL::VertexArrayGL(const gl::VertexArray::Data &data,
                              const FunctionsGL *functions,
                              StateManagerGL *stateManager)
     : VertexArrayImpl(data),
@@ -75,40 +64,29 @@
     }
 }
 
-gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
-                                             GLint first,
-                                             GLsizei count) const
+gl::Error VertexArrayGL::syncDrawArraysState(const std::vector<GLuint> &activeAttribLocations, GLint first, GLsizei count) const
 {
-    return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, nullptr);
+    return syncDrawState(activeAttribLocations, first, count, GL_NONE, nullptr, nullptr);
 }
 
-gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
-                                               GLsizei count,
-                                               GLenum type,
-                                               const GLvoid *indices,
-                                               const GLvoid **outIndices) const
+gl::Error VertexArrayGL::syncDrawElementsState(const std::vector<GLuint> &activeAttribLocations, GLsizei count,
+                                               GLenum type, const GLvoid *indices, const GLvoid **outIndices) const
 {
-    return syncDrawState(activeAttributesMask, 0, count, type, indices, outIndices);
+    return syncDrawState(activeAttribLocations, 0, count, type, indices, outIndices);
 }
 
-gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
-                                       GLint first,
-                                       GLsizei count,
-                                       GLenum type,
-                                       const GLvoid *indices,
-                                       const GLvoid **outIndices) const
+gl::Error VertexArrayGL::syncDrawState(const std::vector<GLuint> &activeAttribLocations, GLint first, GLsizei count, GLenum type, const GLvoid *indices, const GLvoid **outIndices) const
 {
     mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
 
     // Check if any attributes need to be streamed, determines if the index range needs to be computed
-    bool attributesNeedStreaming = mAttributesNeedStreaming.any();
+    bool attributesNeedStreaming = doAttributesNeedStreaming(activeAttribLocations);
 
     // Determine if an index buffer needs to be streamed and the range of vertices that need to be copied
-    RangeUI indexRange(0, 0);
+    gl::RangeUI indexRange(0, 0);
     if (type != GL_NONE)
     {
-        Error error =
-            syncIndexData(count, type, indices, attributesNeedStreaming, &indexRange, outIndices);
+        gl::Error error = syncIndexData(count, type, indices, attributesNeedStreaming, &indexRange, outIndices);
         if (error.isError())
         {
             return error;
@@ -121,24 +99,130 @@
         indexRange.end = first + count;
     }
 
-    if (attributesNeedStreaming)
+    // Sync the vertex attribute state and track what data needs to be streamed
+    size_t streamingDataSize = 0;
+    size_t maxAttributeDataSize = 0;
+    gl::Error error = syncAttributeState(activeAttribLocations, attributesNeedStreaming, indexRange,
+                                         &streamingDataSize, &maxAttributeDataSize);
+    if (error.isError())
     {
-        Error error = streamAttributes(activeAttributesMask, indexRange);
+        return error;
+    }
+
+    if (streamingDataSize > 0)
+    {
+        ASSERT(attributesNeedStreaming);
+
+        error = streamAttributes(activeAttribLocations, streamingDataSize, maxAttributeDataSize,
+                                 indexRange);
         if (error.isError())
         {
             return error;
         }
     }
 
-    return Error(GL_NO_ERROR);
+    return gl::Error(GL_NO_ERROR);
 }
 
-Error VertexArrayGL::syncIndexData(GLsizei count,
-                                   GLenum type,
-                                   const GLvoid *indices,
-                                   bool attributesNeedStreaming,
-                                   RangeUI *outIndexRange,
-                                   const GLvoid **outIndices) const
+bool VertexArrayGL::doAttributesNeedStreaming(const std::vector<GLuint> &activeAttribLocations) const
+{
+    // TODO: if GLES, nothing needs to be streamed
+    const auto &attribs = mData.getVertexAttributes();
+    for (size_t activeAttrib = 0; activeAttrib < activeAttribLocations.size(); activeAttrib++)
+    {
+        GLuint idx = activeAttribLocations[activeAttrib];
+        if (attribs[idx].enabled && attribs[idx].buffer.get() == nullptr)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+gl::Error VertexArrayGL::syncAttributeState(const std::vector<GLuint> &activeAttribLocations, bool attributesNeedStreaming,
+                                            const gl::RangeUI &indexRange,  size_t *outStreamingDataSize, size_t *outMaxAttributeDataSize) const
+{
+    *outStreamingDataSize = 0;
+    *outMaxAttributeDataSize = 0;
+
+    const auto &attribs = mData.getVertexAttributes();
+    for (size_t activeAttrib = 0; activeAttrib < activeAttribLocations.size(); activeAttrib++)
+    {
+        GLuint idx = activeAttribLocations[activeAttrib];
+        const auto &attrib = attribs[idx];
+
+        // Always sync the enabled and divisor state, they are required for both streaming and buffered
+        // attributes
+        if (mAppliedAttributes[idx].enabled != attrib.enabled)
+        {
+            if (attrib.enabled)
+            {
+                mFunctions->enableVertexAttribArray(idx);
+            }
+            else
+            {
+                mFunctions->disableVertexAttribArray(idx);
+            }
+            mAppliedAttributes[idx].enabled = attrib.enabled;
+        }
+        if (mAppliedAttributes[idx].divisor != attrib.divisor)
+        {
+            mFunctions->vertexAttribDivisor(idx, attrib.divisor);
+            mAppliedAttributes[idx].divisor = attrib.divisor;
+        }
+
+        if (attribs[idx].enabled && attrib.buffer.get() == nullptr)
+        {
+            ASSERT(attributesNeedStreaming);
+
+            const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
+
+            // If streaming is going to be required, compute the size of the required buffer
+            // and how much slack space at the beginning of the buffer will be required by determining
+            // the attribute with the largest data size.
+            size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
+            *outStreamingDataSize += typeSize * streamedVertexCount;
+            *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
+        }
+        else
+        {
+            // Sync the attribute with no translation
+            if (mAppliedAttributes[idx] != attrib)
+            {
+                const gl::Buffer *arrayBuffer = attrib.buffer.get();
+                if (arrayBuffer != nullptr)
+                {
+                    const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
+                    mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
+                }
+                else
+                {
+                    mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
+                }
+
+                if (attrib.pureInteger)
+                {
+                    mFunctions->vertexAttribIPointer(idx, attrib.size, attrib.type,
+                                                     attrib.stride, attrib.pointer);
+                }
+                else
+                {
+                    mFunctions->vertexAttribPointer(idx, attrib.size, attrib.type,
+                                                    attrib.normalized, attrib.stride,
+                                                    attrib.pointer);
+                }
+
+                mAppliedAttributes[idx] = attrib;
+            }
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error VertexArrayGL::syncIndexData(GLsizei count, GLenum type, const GLvoid *indices, bool attributesNeedStreaming,
+                                       gl::RangeUI *outIndexRange, const GLvoid **outIndices) const
 {
     ASSERT(outIndices);
 
@@ -158,8 +242,7 @@
         if (attributesNeedStreaming)
         {
             ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
-            Error error = mData.getElementArrayBuffer()->getIndexRange(
-                type, static_cast<size_t>(elementArrayBufferOffset), count, outIndexRange);
+            gl::Error error = mData.getElementArrayBuffer()->getIndexRange(type, static_cast<size_t>(elementArrayBufferOffset), count, outIndexRange);
             if (error.isError())
             {
                 return error;
@@ -177,7 +260,7 @@
         // Only compute the index range if the attributes also need to be streamed
         if (attributesNeedStreaming)
         {
-            *outIndexRange = ComputeIndexRange(type, indices, count);
+            *outIndexRange = gl::ComputeIndexRange(type, indices, count);
         }
 
         // Allocate the streaming element array buffer
@@ -191,7 +274,7 @@
         mAppliedElementArrayBuffer.set(nullptr);
 
         // Make sure the element array buffer is large enough
-        const Type &indexTypeInfo          = GetTypeInfo(type);
+        const gl::Type &indexTypeInfo = gl::GetTypeInfo(type);
         size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
         if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
         {
@@ -209,51 +292,12 @@
         *outIndices = nullptr;
     }
 
-    return Error(GL_NO_ERROR);
+    return gl::Error(GL_NO_ERROR);
 }
 
-void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
-                                                   const gl::RangeUI &indexRange,
-                                                   size_t *outStreamingDataSize,
-                                                   size_t *outMaxAttributeDataSize) const
+gl::Error VertexArrayGL::streamAttributes(const std::vector<GLuint> &activeAttribLocations, size_t streamingDataSize,
+                                          size_t maxAttributeDataSize, const gl::RangeUI &indexRange) const
 {
-    *outStreamingDataSize    = 0;
-    *outMaxAttributeDataSize = 0;
-
-    ASSERT(mAttributesNeedStreaming.any());
-
-    const auto &attribs = mData.getVertexAttributes();
-    for (unsigned int idx : angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
-    {
-        const auto &attrib = attribs[idx];
-        ASSERT(AttributeNeedsStreaming(attrib));
-
-        const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
-
-        // If streaming is going to be required, compute the size of the required buffer
-        // and how much slack space at the beginning of the buffer will be required by determining
-        // the attribute with the largest data size.
-        size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
-        *outStreamingDataSize += typeSize * streamedVertexCount;
-        *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
-    }
-}
-
-gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
-                                          const gl::RangeUI &indexRange) const
-{
-    // Sync the vertex attribute state and track what data needs to be streamed
-    size_t streamingDataSize    = 0;
-    size_t maxAttributeDataSize = 0;
-
-    computeStreamingAttributeSizes(activeAttributesMask, indexRange, &streamingDataSize,
-                                   &maxAttributeDataSize);
-
-    if (streamingDataSize == 0)
-    {
-        return gl::Error(GL_NO_ERROR);
-    }
-
     if (mStreamingArrayBuffer == 0)
     {
         mFunctions->genBuffers(1, &mStreamingArrayBuffer);
@@ -285,48 +329,52 @@
         const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
 
         const auto &attribs = mData.getVertexAttributes();
-        for (unsigned int idx :
-             angle::IterateBitSet(mAttributesNeedStreaming & activeAttributesMask))
+        for (size_t activeAttrib = 0; activeAttrib < activeAttribLocations.size(); activeAttrib++)
         {
+            GLuint idx = activeAttribLocations[activeAttrib];
             const auto &attrib = attribs[idx];
-            ASSERT(AttributeNeedsStreaming(attrib));
 
-            const size_t sourceStride = ComputeVertexAttributeStride(attrib);
-            const size_t destStride   = ComputeVertexAttributeTypeSize(attrib);
-
-            const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer);
-
-            // Pack the data when copying it, user could have supplied a very large stride that
-            // would cause the buffer to be much larger than needed.
-            if (destStride == sourceStride)
+            if (attrib.enabled && attrib.buffer.get() == nullptr)
             {
-                // Can copy in one go, the data is packed
-                memcpy(bufferPointer + curBufferOffset,
-                       inputPointer + (sourceStride * indexRange.start),
-                       destStride * streamedVertexCount);
-            }
-            else
-            {
-                // Copy each vertex individually
-                for (size_t vertexIdx = indexRange.start; vertexIdx <= indexRange.end; vertexIdx++)
+                const size_t sourceStride = ComputeVertexAttributeStride(attrib);
+                const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
+
+                const uint8_t *inputPointer = reinterpret_cast<const uint8_t*>(attrib.pointer);
+
+                // Pack the data when copying it, user could have supplied a very large stride that would
+                // cause the buffer to be much larger than needed.
+                if (destStride == sourceStride)
                 {
-                    memcpy(bufferPointer + curBufferOffset + (destStride * vertexIdx),
-                           inputPointer + (sourceStride * vertexIdx), destStride);
+                    // Can copy in one go, the data is packed
+                    memcpy(bufferPointer + curBufferOffset,
+                           inputPointer + (sourceStride * indexRange.start),
+                           destStride * streamedVertexCount);
                 }
+                else
+                {
+                    // Copy each vertex individually
+                    for (size_t vertexIdx = indexRange.start; vertexIdx <= indexRange.end; vertexIdx++)
+                    {
+                        memcpy(bufferPointer + curBufferOffset + (destStride * vertexIdx),
+                               inputPointer + (sourceStride * vertexIdx),
+                               destStride);
+                    }
+                }
+
+                // Compute where the 0-index vertex would be.
+                const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride);
+
+                mFunctions->vertexAttribPointer(
+                    idx, attrib.size, attrib.type, attrib.normalized,
+                    static_cast<GLsizei>(destStride),
+                    reinterpret_cast<const GLvoid *>(vertexStartOffset));
+
+                curBufferOffset += destStride * streamedVertexCount;
+
+                // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
+                // need to be streamed later, there is no chance that the caching will skip it.
+                mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
             }
-
-            // Compute where the 0-index vertex would be.
-            const size_t vertexStartOffset = curBufferOffset - (indexRange.start * destStride);
-
-            mFunctions->vertexAttribPointer(idx, attrib.size, attrib.type, attrib.normalized,
-                                            static_cast<GLsizei>(destStride),
-                                            reinterpret_cast<const GLvoid *>(vertexStartOffset));
-
-            curBufferOffset += destStride * streamedVertexCount;
-
-            // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
-            // need to be streamed later, there is no chance that the caching will skip it.
-            mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
         }
 
         unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
@@ -334,10 +382,10 @@
 
     if (unmapResult != GL_TRUE)
     {
-        return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
     }
 
-    return Error(GL_NO_ERROR);
+    return gl::Error(GL_NO_ERROR);
 }
 
 GLuint VertexArrayGL::getVertexArrayID() const
@@ -355,114 +403,4 @@
     return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
 }
 
-void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
-{
-    const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
-    mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib));
 }
-
-void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
-{
-    const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
-    if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
-    {
-        return;
-    }
-
-    updateNeedsStreaming(attribIndex);
-
-    mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
-    if (attrib.enabled)
-    {
-        mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
-    }
-    else
-    {
-        mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
-    }
-    mAppliedAttributes[attribIndex].enabled = attrib.enabled;
-}
-
-void VertexArrayGL::updateAttribPointer(size_t attribIndex)
-{
-    const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
-    if (mAppliedAttributes[attribIndex] == attrib)
-    {
-        return;
-    }
-
-    updateNeedsStreaming(attribIndex);
-    mAppliedAttributes[attribIndex] = attrib;
-
-    // If we need to stream, defer the attribPointer to the draw call.
-    if (mAttributesNeedStreaming[attribIndex])
-    {
-        return;
-    }
-
-    mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
-    const Buffer *arrayBuffer = attrib.buffer.get();
-    if (arrayBuffer != nullptr)
-    {
-        const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
-        mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
-    }
-    else
-    {
-        mStateManager->bindBuffer(GL_ARRAY_BUFFER, 0);
-    }
-
-    if (attrib.pureInteger)
-    {
-        mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
-                                         attrib.stride, attrib.pointer);
-    }
-    else
-    {
-        mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
-                                        attrib.normalized, attrib.stride, attrib.pointer);
-    }
-}
-
-void VertexArrayGL::syncState(const VertexArray::DirtyBits &dirtyBits)
-{
-    for (unsigned long dirtyBit : angle::IterateBitSet(dirtyBits))
-    {
-        if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
-        {
-            // TODO(jmadill): Element array buffer bindings
-        }
-        else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
-                 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
-        {
-            size_t attribIndex =
-                static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED;
-            updateAttribEnabled(attribIndex);
-        }
-        else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
-                 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
-        {
-            size_t attribIndex =
-                static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER;
-            updateAttribPointer(attribIndex);
-        }
-        else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR &&
-                 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_DIVISOR)
-        {
-            size_t attribIndex =
-                static_cast<size_t>(dirtyBit) - VertexArray::DIRTY_BIT_ATTRIB_0_DIVISOR;
-            const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
-
-            if (mAppliedAttributes[attribIndex].divisor != attrib.divisor)
-            {
-                mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
-                mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), attrib.divisor);
-                mAppliedAttributes[attribIndex].divisor = attrib.divisor;
-            }
-        }
-        else
-            UNREACHABLE();
-    }
-}
-
-}  // rx