Move Buffer Subject/Observer to front end.
This makes BufferImpl into an Observer Subject. It also refactors
the Vertex Array updates for the D3D11 backend use more of a dirty
bit coding style.
This change makes it so Buffer contents changes trigger front-end
dirty bits from the back-end, which may be undesirable.
Bug: angleproject:2389
Change-Id: Iac8ce1171284a86851c18cd1373ddf24fcefe40b
Reviewed-on: https://chromium-review.googlesource.com/979812
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp
index 19fedee..0735c2a 100644
--- a/src/libANGLE/VertexArray.cpp
+++ b/src/libANGLE/VertexArray.cpp
@@ -9,6 +9,7 @@
#include "libANGLE/VertexArray.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Context.h"
+#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/VertexArrayImpl.h"
@@ -36,8 +37,13 @@
size_t maxAttribBindings)
: mId(id),
mState(maxAttribs, maxAttribBindings),
- mVertexArray(factory->createVertexArray(mState))
+ mVertexArray(factory->createVertexArray(mState)),
+ mElementArrayBufferObserverBinding(this, maxAttribBindings)
{
+ for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
+ {
+ mArrayBufferObserverBindings.emplace_back(this, attribIndex);
+ }
}
void VertexArray::onDestroy(const Context *context)
@@ -140,6 +146,8 @@
binding->setBuffer(context, boundBuffer, isBound);
binding->setOffset(offset);
binding->setStride(stride);
+
+ updateObserverBinding(bindingIndex);
}
void VertexArray::bindVertexBuffer(const Context *context,
@@ -267,6 +275,7 @@
mState.mElementArrayBuffer.set(context, buffer);
if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
+ mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
}
@@ -274,9 +283,11 @@
{
if (mDirtyBits.any())
{
+ mDirtyBitsGuard = mDirtyBits;
ANGLE_TRY(
mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
mDirtyBits.reset();
+ mDirtyBitsGuard.reset();
// This is a bit of an implementation hack - but since we know the implementation
// details of the dirty bit class it should always have the same effect as iterating
@@ -298,4 +309,39 @@
}
}
+VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
+ angle::SubjectIndex index) const
+{
+ if (index == mArrayBufferObserverBindings.size())
+ {
+ return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
+ : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
+ }
+ else
+ {
+ // Note: this currently just gets the top-level dirty bit.
+ ASSERT(index < mArrayBufferObserverBindings.size());
+ return static_cast<DirtyBitType>(
+ (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
+ }
+}
+
+void VertexArray::onSubjectStateChange(const gl::Context *context,
+ angle::SubjectIndex index,
+ angle::SubjectMessage message)
+{
+ bool contentsChanged = (message == angle::SubjectMessage::CONTENTS_CHANGED);
+ DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
+ ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
+ mDirtyBits.set(dirtyBit);
+ context->getGLState().setVertexArrayDirty(this);
+}
+
+void VertexArray::updateObserverBinding(size_t bindingIndex)
+{
+ Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
+ mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
+ : nullptr);
+}
+
} // namespace gl