VertexArray: Cache element limit for buffer checks.
Uses checked math in VertexAttribute updates to store an element limit.
This computes more when changing the vertex array rather than at draw
call time. There may be a performance regression for workflows such as:
loop() {
VertexAttribPointer
DrawArrays
}
It should improve performance in most other cases.
Bug: angleproject:1391
Change-Id: I210d666d9dae9164a1c65f70f5e2151fb4f2d86d
Reviewed-on: https://chromium-review.googlesource.com/1150514
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp
index 2ef2eab..18885be 100644
--- a/src/libANGLE/VertexArray.cpp
+++ b/src/libANGLE/VertexArray.cpp
@@ -51,8 +51,10 @@
{
ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
+ VertexAttribute &attrib = mVertexAttributes[attribIndex];
+
// Update the binding-attribute map.
- const GLuint oldBindingIndex = mVertexAttributes[attribIndex].bindingIndex;
+ const GLuint oldBindingIndex = attrib.bindingIndex;
ASSERT(oldBindingIndex != newBindingIndex);
ASSERT(mVertexBindings[oldBindingIndex].getBoundAttributesMask().test(attribIndex) &&
@@ -62,7 +64,8 @@
mVertexBindings[newBindingIndex].setBoundAttribute(attribIndex);
// Set the attribute using the new binding.
- mVertexAttributes[attribIndex].bindingIndex = newBindingIndex;
+ attrib.bindingIndex = newBindingIndex;
+ attrib.updateCachedElementLimit(mVertexBindings[newBindingIndex]);
}
// VertexArray implementation.
@@ -185,7 +188,7 @@
binding->setStride(stride);
updateObserverBinding(bindingIndex);
- updateCachedBufferBindingSize(bindingIndex);
+ updateCachedBufferBindingSize(binding);
updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
// Update client memory attribute pointers. Affects all bound attributes.
@@ -234,8 +237,16 @@
{
ASSERT(bindingIndex < getMaxBindings());
- mState.mVertexBindings[bindingIndex].setDivisor(divisor);
+ VertexBinding &binding = mState.mVertexBindings[bindingIndex];
+
+ binding.setDivisor(divisor);
setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
+
+ // Trigger updates in all bound attributes.
+ for (size_t attribIndex : binding.getBoundAttributesMask())
+ {
+ mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
+ }
}
void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
@@ -255,7 +266,6 @@
attrib->pureInteger = pureInteger;
attrib->relativeOffset = relativeOffset;
mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
- attrib->updateCachedSizePlusRelativeOffset();
}
void VertexArray::setVertexAttribFormat(size_t attribIndex,
@@ -267,6 +277,9 @@
{
setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
+
+ VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+ attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
}
void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
@@ -281,9 +294,10 @@
{
ASSERT(attribIndex < getMaxAttribs());
- mState.mVertexAttributes[attribIndex].enabled = enabledState;
- mState.mVertexAttributesTypeMask.setIndex(
- GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex);
+ VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+
+ attrib.enabled = enabledState;
+ mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(attrib), attribIndex);
setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
@@ -399,7 +413,7 @@
setDependentDirtyBit(context, false, index);
if (index < mArrayBufferObserverBindings.size())
{
- updateCachedBufferBindingSize(index);
+ updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
}
break;
@@ -434,14 +448,12 @@
: nullptr);
}
-void VertexArray::updateCachedVertexAttributeSize(size_t attribIndex)
+void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
{
- mState.mVertexAttributes[attribIndex].updateCachedSizePlusRelativeOffset();
-}
-
-void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex)
-{
- mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset();
+ for (size_t boundAttribute : binding->getBoundAttributesMask())
+ {
+ mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
+ }
}
void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,