GL: track enabled vertex arrays as a count rather than a mask
authorChris Dalton <csmartdalton@google.com>
Fri, 5 May 2017 13:46:29 +0000 (09:46 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Fri, 5 May 2017 14:29:38 +0000 (14:29 +0000)
Bug: skia:
Change-Id: I46ba29cb32960a415ee1993a7b957ec49c0c56d3
Reviewed-on: https://skia-review.googlesource.com/15520
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLVertexArray.cpp
src/gpu/gl/GrGLVertexArray.h

index 8d76fae..54ce1e9 100644 (file)
@@ -1996,34 +1996,23 @@ void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
         attribState = fHWVertexArrayState.bindInternalVertexArray(this);
     }
 
-    SkASSERT(vertexBuffer);
-    SkASSERT(!vertexBuffer->isMapped());
-
     int vaCount = primProc.numAttribs();
+    attribState->enableVertexArrays(this, vaCount);
+
     if (vaCount > 0) {
+        SkASSERT(vertexBuffer);
+        SkASSERT(!vertexBuffer->isMapped());
 
         GrGLsizei stride = static_cast<GrGLsizei>(primProc.getVertexStride());
-
-        size_t vertexOffsetInBytes = stride * baseVertex;
-
-        vertexOffsetInBytes += vertexBuffer->baseOffset();
-
-        uint32_t usedAttribArraysMask = 0;
-        size_t offset = 0;
+        size_t vertexBufferOffsetInBytes = stride * baseVertex + vertexBuffer->baseOffset();
+        size_t attribOffset = 0;
 
         for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) {
             const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex);
-            usedAttribArraysMask |= (1 << attribIndex);
-            GrVertexAttribType attribType = attrib.fType;
-            attribState->set(this,
-                             attribIndex,
-                             vertexBuffer,
-                             attribType,
-                             stride,
-                             reinterpret_cast<GrGLvoid*>(vertexOffsetInBytes + offset));
-            offset += attrib.fOffset;
+            attribState->set(this, attribIndex, vertexBuffer, attrib.fType, stride,
+                             vertexBufferOffsetInBytes + attribOffset);
+            attribOffset += attrib.fOffset;
         }
-        attribState->disableUnusedArrays(this, usedAttribArraysMask);
     }
 }
 
@@ -3937,9 +3926,9 @@ void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor
     fHWVertexArrayState.setVertexArrayID(this, 0);
 
     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
+    attribs->enableVertexArrays(this, 1);
     attribs->set(this, 0, fWireRectArrayBuffer.get(), kVec2f_GrVertexAttribType,
                  2 * sizeof(GrGLfloat), 0);
-    attribs->disableUnusedArrays(this, 0x1);
 
     GL_CALL(Uniform4fv(fWireRectProgram.fRectUniform, 1, edges));
     GL_CALL(Uniform4fv(fWireRectProgram.fColorUniform, 1, channels));
@@ -3991,9 +3980,9 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
     fHWVertexArrayState.setVertexArrayID(this, 0);
 
     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
+    attribs->enableVertexArrays(this, 1);
     attribs->set(this, 0, fCopyProgramArrayBuffer.get(), kVec2f_GrVertexAttribType,
                  2 * sizeof(GrGLfloat), 0);
-    attribs->disableUnusedArrays(this, 0x1);
 
     // dst rect edges in NDC (-1 to 1)
     int dw = dst->width();
@@ -4232,9 +4221,9 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, bool gammaCorrect) {
     fHWVertexArrayState.setVertexArrayID(this, 0);
 
     GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
+    attribs->enableVertexArrays(this, 1);
     attribs->set(this, 0, fMipmapProgramArrayBuffer.get(), kVec2f_GrVertexAttribType,
                  2 * sizeof(GrGLfloat), 0);
-    attribs->disableUnusedArrays(this, 0x1);
 
     // Set "simple" state once:
     GrXferProcessor::BlendInfo blendInfo;
index 807b9d0..74e609e 100644 (file)
@@ -53,27 +53,23 @@ void GrGLAttribArrayState::set(GrGLGpu* gpu,
                                const GrBuffer* vertexBuffer,
                                GrVertexAttribType type,
                                GrGLsizei stride,
-                               GrGLvoid* offset) {
+                               size_t offsetInBytes) {
     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
     AttribArrayState* array = &fAttribArrayStates[index];
-    if (!array->fEnableIsValid || !array->fEnabled) {
-        GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
-        array->fEnableIsValid = true;
-        array->fEnabled = true;
-    }
     if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
         array->fType != type ||
         array->fStride != stride ||
-        array->fOffset != offset) {
+        array->fOffset != offsetInBytes) {
         gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
         const AttribLayout& layout = attrib_layout(type);
+        const GrGLvoid* offsetAsPtr = reinterpret_cast<const GrGLvoid*>(offsetInBytes);
         if (!GrVertexAttribTypeIsIntType(type)) {
             GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
                                                                layout.fCount,
                                                                layout.fType,
                                                                layout.fNormalized,
                                                                stride,
-                                                               offset));
+                                                               offsetAsPtr));
         } else {
             SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
             SkASSERT(!layout.fNormalized);
@@ -81,30 +77,30 @@ void GrGLAttribArrayState::set(GrGLGpu* gpu,
                                                                 layout.fCount,
                                                                 layout.fType,
                                                                 stride,
-                                                                offset));
+                                                                offsetAsPtr));
         }
         array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
         array->fType = type;
         array->fStride = stride;
-        array->fOffset = offset;
+        array->fOffset = offsetInBytes;
     }
 }
 
-void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
-    int count = fAttribArrayStates.count();
-    for (int i = 0; i < count; ++i) {
-        if (!(usedMask & 0x1)) {
-            if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
-                GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
-                fAttribArrayStates[i].fEnableIsValid = true;
-                fAttribArrayStates[i].fEnabled = false;
-            }
-        } else {
-            SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
-        }
-        // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
-        usedMask >>= 1;
+void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount) {
+    SkASSERT(enabledCount <= fAttribArrayStates.count());
+
+    int firstIdxToEnable = fEnabledCountIsValid ? fNumEnabledArrays : 0;
+    for (int i = firstIdxToEnable; i < enabledCount; ++i) {
+        GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
     }
+
+    int endIdxToDisable = fEnabledCountIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
+    for (int i = enabledCount; i < endIdxToDisable; ++i) {
+        GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
+    }
+
+    fNumEnabledArrays = enabledCount;
+    fEnabledCountIsValid = true;
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
index 4c77d2b..2e951a6 100644 (file)
@@ -44,19 +44,19 @@ public:
              const GrBuffer* vertexBuffer,
              GrVertexAttribType type,
              GrGLsizei stride,
-             GrGLvoid* offset);
+             size_t offsetInBytes);
 
     /**
-     * This function disables vertex attribs not present in the mask. It is assumed that the
-     * GrGLAttribArrayState is tracking the state of the currently bound vertex array object.
+     * This function enables the first 'enabledCount' vertex arrays and disables the rest.
      */
-    void disableUnusedArrays(const GrGLGpu*, uint64_t usedAttribArrayMask);
+    void enableVertexArrays(const GrGLGpu*, int enabledCount);
 
     void invalidate() {
         int count = fAttribArrayStates.count();
         for (int i = 0; i < count; ++i) {
             fAttribArrayStates[i].invalidate();
         }
+        fEnabledCountIsValid = false;
     }
 
     /**
@@ -69,20 +69,17 @@ private:
      * Tracks the state of glVertexAttribArray for an attribute index.
      */
     struct AttribArrayState {
-        void invalidate() {
-            fEnableIsValid = false;
-            fVertexBufferUniqueID.makeInvalid();
-        }
+        void invalidate() { fVertexBufferUniqueID.makeInvalid(); }
 
-        bool                            fEnableIsValid;
-        bool                            fEnabled;
-        GrGpuResource::UniqueID         fVertexBufferUniqueID;
-        GrVertexAttribType              fType;
-        GrGLsizei                       fStride;
-        GrGLvoid*                       fOffset;
+        GrGpuResource::UniqueID   fVertexBufferUniqueID;
+        GrVertexAttribType        fType;
+        GrGLsizei                 fStride;
+        size_t                    fOffset;
     };
 
-    SkSTArray<16, AttribArrayState, true> fAttribArrayStates;
+    SkSTArray<16, AttribArrayState, true>   fAttribArrayStates;
+    int                                     fNumEnabledArrays;
+    bool                                    fEnabledCountIsValid;
 };
 
 /**