Commit cf9383ed by Jamie Madill Committed by Commit Bot

Optimize VertexArray::bindVertexBufferImpl.

Reduces the buffer nullptr checks to a single location. Also optimizes how the transform feedback binding counter is changed. Improves the score of the draw call vertex array change test. Bug: angleproject:3014 Change-Id: I08ff341e08194a407c24143965a3d568e92b97b7 Reviewed-on: https://chromium-review.googlesource.com/c/1406891 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 1a07524d
...@@ -98,9 +98,4 @@ void ObserverBinding::onSubjectReset() ...@@ -98,9 +98,4 @@ void ObserverBinding::onSubjectReset()
{ {
mSubject = nullptr; mSubject = nullptr;
} }
const Subject *ObserverBinding::getSubject() const
{
return mSubject;
}
} // namespace angle } // namespace angle
...@@ -115,7 +115,9 @@ class ObserverBinding final : public ObserverBindingBase ...@@ -115,7 +115,9 @@ class ObserverBinding final : public ObserverBindingBase
void onStateChange(const gl::Context *context, SubjectMessage message) const; void onStateChange(const gl::Context *context, SubjectMessage message) const;
void onSubjectReset() override; void onSubjectReset() override;
const Subject *getSubject() const; ANGLE_INLINE const Subject *getSubject() const { return mSubject; }
ANGLE_INLINE void assignSubject(Subject *subject) { mSubject = subject; }
private: private:
Subject *mSubject; Subject *mSubject;
......
...@@ -140,7 +140,12 @@ void VertexArray::onDestroy(const Context *context) ...@@ -140,7 +140,12 @@ void VertexArray::onDestroy(const Context *context)
bool isBound = context->isCurrentVertexArray(this); bool isBound = context->isCurrentVertexArray(this);
for (VertexBinding &binding : mState.mVertexBindings) for (VertexBinding &binding : mState.mVertexBindings)
{ {
binding.setBuffer(context, nullptr, isBound); if (isBound)
{
if (binding.getBuffer().get())
binding.getBuffer()->onNonTFBindingChanged(-1);
}
binding.setBuffer(context, nullptr);
} }
if (isBound && mState.mElementArrayBuffer.get()) if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onNonTFBindingChanged(-1); mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
...@@ -168,11 +173,18 @@ const std::string &VertexArray::getLabel() const ...@@ -168,11 +173,18 @@ const std::string &VertexArray::getLabel() const
void VertexArray::detachBuffer(const Context *context, GLuint bufferName) void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
{ {
bool isBound = context->isCurrentVertexArray(this); bool isBound = context->isCurrentVertexArray(this);
for (auto &binding : mState.mVertexBindings) for (size_t bindingIndex = 0; bindingIndex < gl::MAX_VERTEX_ATTRIB_BINDINGS; ++bindingIndex)
{ {
VertexBinding &binding = mState.mVertexBindings[bindingIndex];
if (binding.getBuffer().id() == bufferName) if (binding.getBuffer().id() == bufferName)
{ {
binding.setBuffer(context, nullptr, isBound); if (isBound)
{
if (binding.getBuffer().get())
binding.getBuffer()->onNonTFBindingChanged(-1);
}
binding.setBuffer(context, nullptr);
mArrayBufferObserverBindings[bindingIndex].reset();
} }
} }
...@@ -230,22 +242,30 @@ ANGLE_INLINE void VertexArray::updateCachedBufferBindingSize(const Context *cont ...@@ -230,22 +242,30 @@ ANGLE_INLINE void VertexArray::updateCachedBufferBindingSize(const Context *cont
} }
} }
ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffers(VertexBinding *binding) ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffers(
bool isMapped,
const AttributesMask &boundAttributesMask)
{ {
Buffer *buffer = binding->getBuffer().get(); if (isMapped)
if (buffer && buffer->isMapped())
{ {
mState.mCachedMappedArrayBuffers |= binding->getBoundAttributesMask(); mState.mCachedMappedArrayBuffers |= boundAttributesMask;
} }
else else
{ {
mState.mCachedMappedArrayBuffers &= ~binding->getBoundAttributesMask(); mState.mCachedMappedArrayBuffers &= ~boundAttributesMask;
} }
mState.mCachedEnabledMappedArrayBuffers = mState.mCachedEnabledMappedArrayBuffers =
mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask; mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
} }
ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffersBinding(const VertexBinding &binding)
{
const Buffer *buffer = binding.getBuffer().get();
return updateCachedMappedArrayBuffers(buffer && buffer->isMapped(),
binding.getBoundAttributesMask());
}
ANGLE_INLINE void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, ANGLE_INLINE void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
const Buffer *buffer) const Buffer *buffer)
{ {
...@@ -260,27 +280,43 @@ void VertexArray::bindVertexBufferImpl(const Context *context, ...@@ -260,27 +280,43 @@ void VertexArray::bindVertexBufferImpl(const Context *context,
GLsizei stride) GLsizei stride)
{ {
ASSERT(bindingIndex < getMaxBindings()); ASSERT(bindingIndex < getMaxBindings());
bool isBound = context->isCurrentVertexArray(this); ASSERT(context->isCurrentVertexArray(this));
VertexBinding *binding = &mState.mVertexBindings[bindingIndex]; VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
binding->setBuffer(context, boundBuffer, isBound); Buffer *oldBuffer = binding->getBuffer().get();
angle::ObserverBinding *observer = &mArrayBufferObserverBindings[bindingIndex];
observer->assignSubject(boundBuffer);
// Several nullptr checks are combined here for optimization purposes.
if (oldBuffer)
{
oldBuffer->onNonTFBindingChanged(-1);
oldBuffer->removeObserver(observer);
oldBuffer->release(context);
}
binding->assignBuffer(boundBuffer);
binding->setOffset(offset); binding->setOffset(offset);
binding->setStride(stride); binding->setStride(stride);
updateObserverBinding(bindingIndex);
updateCachedBufferBindingSize(context, binding); updateCachedBufferBindingSize(context, binding);
updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
updateCachedMappedArrayBuffers(binding);
// Update client memory attribute pointers. Affects all bound attributes. // Update client memory attribute pointers. Affects all bound attributes.
if (boundBuffer) if (boundBuffer)
{ {
boundBuffer->addRef();
boundBuffer->onNonTFBindingChanged(1);
boundBuffer->addObserver(observer);
mCachedTransformFeedbackConflictedBindingsMask.set(
bindingIndex, boundBuffer->isBoundForTransformFeedbackAndOtherUse());
mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask(); mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
updateCachedMappedArrayBuffers(boundBuffer->isMapped(), binding->getBoundAttributesMask());
} }
else else
{ {
mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, false);
mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask(); mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
updateCachedMappedArrayBuffers(false, binding->getBoundAttributesMask());
} }
} }
...@@ -527,7 +563,7 @@ void VertexArray::onSubjectStateChange(const gl::Context *context, ...@@ -527,7 +563,7 @@ void VertexArray::onSubjectStateChange(const gl::Context *context,
case angle::SubjectMessage::RESOURCE_MAPPED: case angle::SubjectMessage::RESOURCE_MAPPED:
if (!IsElementArrayBufferSubjectIndex(index)) if (!IsElementArrayBufferSubjectIndex(index))
{ {
updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]); updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
} }
onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED); onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
break; break;
...@@ -537,7 +573,7 @@ void VertexArray::onSubjectStateChange(const gl::Context *context, ...@@ -537,7 +573,7 @@ void VertexArray::onSubjectStateChange(const gl::Context *context,
if (!IsElementArrayBufferSubjectIndex(index)) if (!IsElementArrayBufferSubjectIndex(index))
{ {
updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]); updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
} }
onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED); onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
break; break;
...@@ -558,12 +594,6 @@ void VertexArray::setDependentDirtyBit(const gl::Context *context, ...@@ -558,12 +594,6 @@ void VertexArray::setDependentDirtyBit(const gl::Context *context,
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED); onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
} }
void VertexArray::updateObserverBinding(size_t bindingIndex)
{
Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer);
}
bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
{ {
// Fast check first. // Fast check first.
......
...@@ -287,7 +287,6 @@ class VertexArray final : public angle::ObserverInterface, ...@@ -287,7 +287,6 @@ class VertexArray final : public angle::ObserverInterface,
void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit); void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit); void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit);
void updateObserverBinding(size_t bindingIndex);
DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const; DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const;
void setDependentDirtyBit(const gl::Context *context, void setDependentDirtyBit(const gl::Context *context,
bool contentsChanged, bool contentsChanged,
...@@ -296,7 +295,8 @@ class VertexArray final : public angle::ObserverInterface, ...@@ -296,7 +295,8 @@ class VertexArray final : public angle::ObserverInterface,
// These are used to optimize draw call validation. // These are used to optimize draw call validation.
void updateCachedBufferBindingSize(const Context *context, VertexBinding *binding); void updateCachedBufferBindingSize(const Context *context, VertexBinding *binding);
void updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, const Buffer *buffer); void updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, const Buffer *buffer);
void updateCachedMappedArrayBuffers(VertexBinding *binding); void updateCachedMappedArrayBuffers(bool isMapped, const AttributesMask &boundAttributesMask);
void updateCachedMappedArrayBuffersBinding(const VertexBinding &binding);
angle::Result getIndexRangeImpl(const Context *context, angle::Result getIndexRangeImpl(const Context *context,
DrawElementsType type, DrawElementsType type,
......
...@@ -40,18 +40,14 @@ class VertexBinding final : angle::NonCopyable ...@@ -40,18 +40,14 @@ class VertexBinding final : angle::NonCopyable
const BindingPointer<Buffer> &getBuffer() const { return mBuffer; } const BindingPointer<Buffer> &getBuffer() const { return mBuffer; }
ANGLE_INLINE void setBuffer(const gl::Context *context, Buffer *bufferIn, bool containerIsBound) ANGLE_INLINE void setBuffer(const gl::Context *context, Buffer *bufferIn)
{ {
if (containerIsBound)
{
if (mBuffer.get())
mBuffer->onNonTFBindingChanged(-1);
if (bufferIn)
bufferIn->onNonTFBindingChanged(1);
}
mBuffer.set(context, bufferIn); mBuffer.set(context, bufferIn);
} }
// Skips ref counting for better inlined performance.
ANGLE_INLINE void assignBuffer(Buffer *bufferIn) { mBuffer.assign(bufferIn); }
void onContainerBindingChanged(const Context *context, int incr) const; void onContainerBindingChanged(const Context *context, int incr) const;
const AttributesMask &getBoundAttributesMask() const { return mBoundAttributesMask; } const AttributesMask &getBoundAttributesMask() const { return mBoundAttributesMask; }
......
...@@ -98,7 +98,7 @@ void VertexArrayGL::destroy(const gl::Context *context) ...@@ -98,7 +98,7 @@ void VertexArrayGL::destroy(const gl::Context *context)
mAppliedElementArrayBuffer.set(context, nullptr); mAppliedElementArrayBuffer.set(context, nullptr);
for (auto &binding : mAppliedBindings) for (auto &binding : mAppliedBindings)
{ {
binding.setBuffer(context, nullptr, false); binding.setBuffer(context, nullptr);
} }
} }
...@@ -435,7 +435,7 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri ...@@ -435,7 +435,7 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri
{ {
// Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if // Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if
// it starts to use a buffer later, there is no chance that the caching will skip it. // it starts to use a buffer later, there is no chance that the caching will skip it.
mAppliedBindings[attribIndex].setBuffer(context, nullptr, false); mAppliedBindings[attribIndex].setBuffer(context, nullptr);
return; return;
} }
...@@ -474,7 +474,7 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri ...@@ -474,7 +474,7 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri
mAppliedBindings[attribIndex].setStride(binding.getStride()); mAppliedBindings[attribIndex].setStride(binding.getStride());
mAppliedBindings[attribIndex].setOffset(binding.getOffset()); mAppliedBindings[attribIndex].setOffset(binding.getOffset());
mAppliedBindings[attribIndex].setBuffer(context, binding.getBuffer().get(), false); mAppliedBindings[attribIndex].setBuffer(context, binding.getBuffer().get());
} }
void VertexArrayGL::callVertexAttribPointer(GLuint attribIndex, void VertexArrayGL::callVertexAttribPointer(GLuint attribIndex,
...@@ -569,7 +569,7 @@ void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindi ...@@ -569,7 +569,7 @@ void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindi
mAppliedBindings[bindingIndex].setStride(binding.getStride()); mAppliedBindings[bindingIndex].setStride(binding.getStride());
mAppliedBindings[bindingIndex].setOffset(binding.getOffset()); mAppliedBindings[bindingIndex].setOffset(binding.getOffset());
mAppliedBindings[bindingIndex].setBuffer(context, binding.getBuffer().get(), false); mAppliedBindings[bindingIndex].setBuffer(context, binding.getBuffer().get());
} }
void VertexArrayGL::updateBindingDivisor(size_t bindingIndex) void VertexArrayGL::updateBindingDivisor(size_t bindingIndex)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment