Commit 7267aa65 by Jamie Madill Committed by Commit Bot

Optimize ValidateDrawAttribs: Part 3.

This is a small optimization for the WebGL compatibility mode. Instead of scanning the list of attributes for a Transform feedback conflict, it can quickly check a cached mask. This should save a lot of cycles on the fast path. Bug: angleproject:1391 Change-Id: Icb8d095493a629dbff0e93872357e5bf7c7458ae Reviewed-on: https://chromium-review.googlesource.com/1011236 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 1633663b
...@@ -243,7 +243,7 @@ bool Buffer::isBoundForTransformFeedbackAndOtherUse() const ...@@ -243,7 +243,7 @@ bool Buffer::isBoundForTransformFeedbackAndOtherUse() const
mState.mTransformFeedbackBindingCount != mState.mBindingCount; mState.mTransformFeedbackBindingCount != mState.mBindingCount;
} }
void Buffer::onBindingChanged(bool bound, BufferBinding target) void Buffer::onBindingChanged(const Context *context, bool bound, BufferBinding target)
{ {
ASSERT(bound || mState.mBindingCount > 0); ASSERT(bound || mState.mBindingCount > 0);
mState.mBindingCount += bound ? 1 : -1; mState.mBindingCount += bound ? 1 : -1;
...@@ -251,6 +251,8 @@ void Buffer::onBindingChanged(bool bound, BufferBinding target) ...@@ -251,6 +251,8 @@ void Buffer::onBindingChanged(bool bound, BufferBinding target)
{ {
ASSERT(bound || mState.mTransformFeedbackBindingCount > 0); ASSERT(bound || mState.mTransformFeedbackBindingCount > 0);
mState.mTransformFeedbackBindingCount += bound ? 1 : -1; mState.mTransformFeedbackBindingCount += bound ? 1 : -1;
mImpl->onStateChange(context, angle::SubjectMessage::BINDING_CHANGED);
} }
} }
......
...@@ -116,7 +116,7 @@ class Buffer final : public RefCountObject, public LabeledObject ...@@ -116,7 +116,7 @@ class Buffer final : public RefCountObject, public LabeledObject
bool isBound() const; bool isBound() const;
bool isBoundForTransformFeedbackAndOtherUse() const; bool isBoundForTransformFeedbackAndOtherUse() const;
void onBindingChanged(bool bound, BufferBinding target); void onBindingChanged(const Context *context, bool bound, BufferBinding target);
private: private:
BufferState mState; BufferState mState;
......
...@@ -1012,7 +1012,7 @@ void Context::bindDrawFramebuffer(GLuint framebufferHandle) ...@@ -1012,7 +1012,7 @@ void Context::bindDrawFramebuffer(GLuint framebufferHandle)
void Context::bindVertexArray(GLuint vertexArrayHandle) void Context::bindVertexArray(GLuint vertexArrayHandle)
{ {
VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle); VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
mGLState.setVertexArrayBinding(vertexArray); mGLState.setVertexArrayBinding(this, vertexArray);
} }
void Context::bindVertexBuffer(GLuint bindingIndex, void Context::bindVertexBuffer(GLuint bindingIndex,
...@@ -2669,7 +2669,7 @@ void Context::detachVertexArray(GLuint vertexArray) ...@@ -2669,7 +2669,7 @@ void Context::detachVertexArray(GLuint vertexArray)
// [OpenGL ES 3.0.2] section 2.10 page 43: // [OpenGL ES 3.0.2] section 2.10 page 43:
// If a vertex array object that is currently bound is deleted, the binding // If a vertex array object that is currently bound is deleted, the binding
// for that object reverts to zero and the default vertex array becomes current. // for that object reverts to zero and the default vertex array becomes current.
if (mGLState.removeVertexArrayBinding(vertexArray)) if (mGLState.removeVertexArrayBinding(this, vertexArray))
{ {
bindVertexArray(0); bindVertexArray(0);
} }
......
...@@ -30,6 +30,7 @@ enum class SubjectMessage ...@@ -30,6 +30,7 @@ enum class SubjectMessage
{ {
CONTENTS_CHANGED, CONTENTS_CHANGED,
STORAGE_CHANGED, STORAGE_CHANGED,
BINDING_CHANGED,
DEPENDENT_DIRTY_BITS, DEPENDENT_DIRTY_BITS,
}; };
......
...@@ -45,10 +45,10 @@ void UpdateBufferBinding(const Context *context, ...@@ -45,10 +45,10 @@ void UpdateBufferBinding(const Context *context,
BufferBinding target) BufferBinding target)
{ {
if (binding->get()) if (binding->get())
(*binding)->onBindingChanged(false, target); (*binding)->onBindingChanged(context, false, target);
binding->set(context, buffer); binding->set(context, buffer);
if (binding->get()) if (binding->get())
(*binding)->onBindingChanged(true, target); (*binding)->onBindingChanged(context, true, target);
} }
void UpdateBufferBinding(const Context *context, void UpdateBufferBinding(const Context *context,
...@@ -59,10 +59,10 @@ void UpdateBufferBinding(const Context *context, ...@@ -59,10 +59,10 @@ void UpdateBufferBinding(const Context *context,
GLsizeiptr size) GLsizeiptr size)
{ {
if (binding->get()) if (binding->get())
(*binding)->onBindingChanged(false, target); (*binding)->onBindingChanged(context, false, target);
binding->set(context, buffer, offset, size); binding->set(context, buffer, offset, size);
if (binding->get()) if (binding->get())
(*binding)->onBindingChanged(true, target); (*binding)->onBindingChanged(context, true, target);
} }
State::State() State::State()
...@@ -291,7 +291,7 @@ void State::reset(const Context *context) ...@@ -291,7 +291,7 @@ void State::reset(const Context *context)
mProgramPipeline.set(context, nullptr); mProgramPipeline.set(context, nullptr);
if (mTransformFeedback.get()) if (mTransformFeedback.get())
mTransformFeedback->onBindingChanged(false); mTransformFeedback->onBindingChanged(context, false);
mTransformFeedback.set(context, nullptr); mTransformFeedback.set(context, nullptr);
for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
...@@ -1165,15 +1165,15 @@ bool State::removeDrawFramebufferBinding(GLuint framebuffer) ...@@ -1165,15 +1165,15 @@ bool State::removeDrawFramebufferBinding(GLuint framebuffer)
return false; return false;
} }
void State::setVertexArrayBinding(VertexArray *vertexArray) void State::setVertexArrayBinding(const Context *context, VertexArray *vertexArray)
{ {
if (mVertexArray == vertexArray) if (mVertexArray == vertexArray)
return; return;
if (mVertexArray) if (mVertexArray)
mVertexArray->onBindingChanged(false); mVertexArray->onBindingChanged(context, false);
mVertexArray = vertexArray; mVertexArray = vertexArray;
if (vertexArray) if (vertexArray)
vertexArray->onBindingChanged(true); vertexArray->onBindingChanged(context, true);
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
if (mVertexArray && mVertexArray->hasAnyDirtyBit()) if (mVertexArray && mVertexArray->hasAnyDirtyBit())
...@@ -1194,11 +1194,11 @@ VertexArray *State::getVertexArray() const ...@@ -1194,11 +1194,11 @@ VertexArray *State::getVertexArray() const
return mVertexArray; return mVertexArray;
} }
bool State::removeVertexArrayBinding(GLuint vertexArray) bool State::removeVertexArrayBinding(const Context *context, GLuint vertexArray)
{ {
if (mVertexArray && mVertexArray->id() == vertexArray) if (mVertexArray && mVertexArray->id() == vertexArray)
{ {
mVertexArray->onBindingChanged(false); mVertexArray->onBindingChanged(context, false);
mVertexArray = nullptr; mVertexArray = nullptr;
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
...@@ -1274,10 +1274,10 @@ void State::setTransformFeedbackBinding(const Context *context, ...@@ -1274,10 +1274,10 @@ void State::setTransformFeedbackBinding(const Context *context,
if (transformFeedback == mTransformFeedback.get()) if (transformFeedback == mTransformFeedback.get())
return; return;
if (mTransformFeedback.get()) if (mTransformFeedback.get())
mTransformFeedback->onBindingChanged(false); mTransformFeedback->onBindingChanged(context, false);
mTransformFeedback.set(context, transformFeedback); mTransformFeedback.set(context, transformFeedback);
if (mTransformFeedback.get()) if (mTransformFeedback.get())
mTransformFeedback->onBindingChanged(true); mTransformFeedback->onBindingChanged(context, true);
mDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING); mDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
} }
...@@ -1298,7 +1298,7 @@ bool State::removeTransformFeedbackBinding(const Context *context, GLuint transf ...@@ -1298,7 +1298,7 @@ bool State::removeTransformFeedbackBinding(const Context *context, GLuint transf
if (mTransformFeedback.id() == transformFeedback) if (mTransformFeedback.id() == transformFeedback)
{ {
if (mTransformFeedback.get()) if (mTransformFeedback.get())
mTransformFeedback->onBindingChanged(false); mTransformFeedback->onBindingChanged(context, false);
mTransformFeedback.set(context, nullptr); mTransformFeedback.set(context, nullptr);
return true; return true;
} }
......
...@@ -204,10 +204,10 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -204,10 +204,10 @@ class State : public angle::ObserverInterface, angle::NonCopyable
bool removeDrawFramebufferBinding(GLuint framebuffer); bool removeDrawFramebufferBinding(GLuint framebuffer);
// Vertex array object binding manipulation // Vertex array object binding manipulation
void setVertexArrayBinding(VertexArray *vertexArray); void setVertexArrayBinding(const Context *context, VertexArray *vertexArray);
GLuint getVertexArrayId() const; GLuint getVertexArrayId() const;
VertexArray *getVertexArray() const; VertexArray *getVertexArray() const;
bool removeVertexArrayBinding(GLuint vertexArray); bool removeVertexArrayBinding(const Context *context, GLuint vertexArray);
// Program binding manipulation // Program binding manipulation
void setProgram(const Context *context, Program *newProgram); void setProgram(const Context *context, Program *newProgram);
......
...@@ -238,7 +238,7 @@ void TransformFeedback::detachBuffer(const Context *context, GLuint bufferName) ...@@ -238,7 +238,7 @@ void TransformFeedback::detachBuffer(const Context *context, GLuint bufferName)
{ {
if (isBound) if (isBound)
{ {
mState.mIndexedBuffers[index]->onBindingChanged(false, mState.mIndexedBuffers[index]->onBindingChanged(context, false,
BufferBinding::TransformFeedback); BufferBinding::TransformFeedback);
} }
mState.mIndexedBuffers[index].set(context, nullptr); mState.mIndexedBuffers[index].set(context, nullptr);
...@@ -257,12 +257,13 @@ void TransformFeedback::bindIndexedBuffer(const Context *context, ...@@ -257,12 +257,13 @@ void TransformFeedback::bindIndexedBuffer(const Context *context,
bool isBound = context && context->isCurrentTransformFeedback(this); bool isBound = context && context->isCurrentTransformFeedback(this);
if (isBound && mState.mIndexedBuffers[index].get()) if (isBound && mState.mIndexedBuffers[index].get())
{ {
mState.mIndexedBuffers[index]->onBindingChanged(false, BufferBinding::TransformFeedback); mState.mIndexedBuffers[index]->onBindingChanged(context, false,
BufferBinding::TransformFeedback);
} }
mState.mIndexedBuffers[index].set(context, buffer, offset, size); mState.mIndexedBuffers[index].set(context, buffer, offset, size);
if (isBound && buffer) if (isBound && buffer)
{ {
buffer->onBindingChanged(true, BufferBinding::TransformFeedback); buffer->onBindingChanged(context, true, BufferBinding::TransformFeedback);
} }
mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]); mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
...@@ -301,14 +302,14 @@ const rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const ...@@ -301,14 +302,14 @@ const rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const
return mImplementation; return mImplementation;
} }
void TransformFeedback::onBindingChanged(bool bound) void TransformFeedback::onBindingChanged(const Context *context, bool bound)
{ {
for (auto &buffer : mState.mIndexedBuffers) for (auto &buffer : mState.mIndexedBuffers)
{ {
if (buffer.get()) if (buffer.get())
{ {
buffer->onBindingChanged(bound, BufferBinding::TransformFeedback); buffer->onBindingChanged(context, bound, BufferBinding::TransformFeedback);
} }
} }
} }
} } // namespace gl
...@@ -97,15 +97,15 @@ class TransformFeedback final : public RefCountObject, public LabeledObject ...@@ -97,15 +97,15 @@ class TransformFeedback final : public RefCountObject, public LabeledObject
rx::TransformFeedbackImpl *getImplementation(); rx::TransformFeedbackImpl *getImplementation();
const rx::TransformFeedbackImpl *getImplementation() const; const rx::TransformFeedbackImpl *getImplementation() const;
void onBindingChanged(bool bound); void onBindingChanged(const Context *context, bool bound);
private: private:
void bindProgram(const Context *context, Program *program); void bindProgram(const Context *context, Program *program);
TransformFeedbackState mState; TransformFeedbackState mState;
rx::TransformFeedbackImpl* mImplementation; rx::TransformFeedbackImpl *mImplementation;
}; };
} } // namespace gl
#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_ #endif // LIBANGLE_TRANSFORM_FEEDBACK_H_
...@@ -65,7 +65,7 @@ void VertexArray::onDestroy(const Context *context) ...@@ -65,7 +65,7 @@ void VertexArray::onDestroy(const Context *context)
binding.setBuffer(context, nullptr, isBound); binding.setBuffer(context, nullptr, isBound);
} }
if (isBound && mState.mElementArrayBuffer.get()) if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray); mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray);
mState.mElementArrayBuffer.set(context, nullptr); mState.mElementArrayBuffer.set(context, nullptr);
mVertexArray->destroy(context); mVertexArray->destroy(context);
SafeDelete(mVertexArray); SafeDelete(mVertexArray);
...@@ -106,7 +106,7 @@ void VertexArray::detachBuffer(const Context *context, GLuint bufferName) ...@@ -106,7 +106,7 @@ void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
if (mState.mElementArrayBuffer.id() == bufferName) if (mState.mElementArrayBuffer.id() == bufferName)
{ {
if (isBound && mState.mElementArrayBuffer.get()) if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::Array); mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::Array);
mState.mElementArrayBuffer.set(context, nullptr); mState.mElementArrayBuffer.set(context, nullptr);
} }
} }
...@@ -160,6 +160,7 @@ void VertexArray::bindVertexBufferImpl(const Context *context, ...@@ -160,6 +160,7 @@ void VertexArray::bindVertexBufferImpl(const Context *context,
updateObserverBinding(bindingIndex); updateObserverBinding(bindingIndex);
updateCachedBufferBindingSize(bindingIndex); updateCachedBufferBindingSize(bindingIndex);
updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
} }
void VertexArray::bindVertexBuffer(const Context *context, void VertexArray::bindVertexBuffer(const Context *context,
...@@ -287,10 +288,10 @@ void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer) ...@@ -287,10 +288,10 @@ void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
{ {
bool isBound = context->isCurrentVertexArray(this); bool isBound = context->isCurrentVertexArray(this);
if (isBound && mState.mElementArrayBuffer.get()) if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(false, BufferBinding::ElementArray); mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray);
mState.mElementArrayBuffer.set(context, buffer); mState.mElementArrayBuffer.set(context, buffer);
if (isBound && mState.mElementArrayBuffer.get()) if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray); mState.mElementArrayBuffer->onBindingChanged(context, true, BufferBinding::ElementArray);
mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr); mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
} }
...@@ -315,13 +316,13 @@ gl::Error VertexArray::syncState(const Context *context) ...@@ -315,13 +316,13 @@ gl::Error VertexArray::syncState(const Context *context)
return gl::NoError(); return gl::NoError();
} }
void VertexArray::onBindingChanged(bool bound) void VertexArray::onBindingChanged(const Context *context, bool bound)
{ {
if (mState.mElementArrayBuffer.get()) if (mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(bound, BufferBinding::ElementArray); mState.mElementArrayBuffer->onBindingChanged(context, bound, BufferBinding::ElementArray);
for (auto &binding : mState.mVertexBindings) for (auto &binding : mState.mVertexBindings)
{ {
binding.onContainerBindingChanged(bound); binding.onContainerBindingChanged(context, bound);
} }
} }
...@@ -346,17 +347,42 @@ void VertexArray::onSubjectStateChange(const gl::Context *context, ...@@ -346,17 +347,42 @@ void VertexArray::onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index, angle::SubjectIndex index,
angle::SubjectMessage message) angle::SubjectMessage message)
{ {
bool contentsChanged = (message == angle::SubjectMessage::CONTENTS_CHANGED); switch (message)
{
case angle::SubjectMessage::CONTENTS_CHANGED:
setDependentDirtyBit(context, true, index);
break;
case angle::SubjectMessage::STORAGE_CHANGED:
setDependentDirtyBit(context, false, index);
if (index < mArrayBufferObserverBindings.size())
{
updateCachedBufferBindingSize(index);
}
break;
case angle::SubjectMessage::BINDING_CHANGED:
if (index < mArrayBufferObserverBindings.size())
{
const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
updateCachedTransformFeedbackBindingValidation(index, buffer);
}
break;
default:
UNREACHABLE();
break;
}
}
void VertexArray::setDependentDirtyBit(const gl::Context *context,
bool contentsChanged,
angle::SubjectIndex index)
{
DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index); DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit)); ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
mDirtyBits.set(dirtyBit); mDirtyBits.set(dirtyBit);
context->getGLState().setVertexArrayDirty(this); context->getGLState().setVertexArrayDirty(this);
if (message == angle::SubjectMessage::STORAGE_CHANGED &&
index < mArrayBufferObserverBindings.size())
{
updateCachedBufferBindingSize(index);
}
} }
void VertexArray::updateObserverBinding(size_t bindingIndex) void VertexArray::updateObserverBinding(size_t bindingIndex)
...@@ -376,4 +402,32 @@ void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex) ...@@ -376,4 +402,32 @@ void VertexArray::updateCachedBufferBindingSize(size_t bindingIndex)
mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset(); mState.mVertexBindings[bindingIndex].updateCachedBufferSizeMinusOffset();
} }
void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
const Buffer *buffer)
{
const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
}
bool VertexArray::hasTransformFeedbackBindingConflict(const AttributesMask &activeAttribues) const
{
// Fast check first.
if (!mCachedTransformFeedbackConflictedBindingsMask.any())
{
return false;
}
// Slow check. We must ensure that the conflicting attributes are enabled/active.
for (size_t attribIndex : activeAttribues)
{
const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
{
return true;
}
}
return false;
}
} // namespace gl } // namespace gl
...@@ -244,7 +244,8 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject ...@@ -244,7 +244,8 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject
ComponentTypeMask getAttributesTypeMask() const { return mState.mVertexAttributesTypeMask; } ComponentTypeMask getAttributesTypeMask() const { return mState.mVertexAttributesTypeMask; }
AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; } AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; }
void onBindingChanged(bool bound); void onBindingChanged(const Context *context, bool bound);
bool hasTransformFeedbackBindingConflict(const AttributesMask &activeAttribues) const;
private: private:
~VertexArray() override; ~VertexArray() override;
...@@ -254,10 +255,14 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject ...@@ -254,10 +255,14 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject
void updateObserverBinding(size_t bindingIndex); 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,
bool contentsChanged,
angle::SubjectIndex index);
// These are used to optimize draw call validation. // These are used to optimize draw call validation.
void updateCachedVertexAttributeSize(size_t attribIndex); void updateCachedVertexAttributeSize(size_t attribIndex);
void updateCachedBufferBindingSize(size_t bindingIndex); void updateCachedBufferBindingSize(size_t bindingIndex);
void updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, const Buffer *buffer);
GLuint mId; GLuint mId;
...@@ -271,6 +276,8 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject ...@@ -271,6 +276,8 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject
std::vector<angle::ObserverBinding> mArrayBufferObserverBindings; std::vector<angle::ObserverBinding> mArrayBufferObserverBindings;
angle::ObserverBinding mElementArrayBufferObserverBinding; angle::ObserverBinding mElementArrayBufferObserverBinding;
AttributesMask mCachedTransformFeedbackConflictedBindingsMask;
}; };
} // namespace gl } // namespace gl
......
...@@ -43,16 +43,16 @@ VertexBinding &VertexBinding::operator=(VertexBinding &&binding) ...@@ -43,16 +43,16 @@ VertexBinding &VertexBinding::operator=(VertexBinding &&binding)
void VertexBinding::setBuffer(const gl::Context *context, Buffer *bufferIn, bool containerIsBound) void VertexBinding::setBuffer(const gl::Context *context, Buffer *bufferIn, bool containerIsBound)
{ {
if (mBuffer.get() && containerIsBound) if (mBuffer.get() && containerIsBound)
mBuffer->onBindingChanged(false, BufferBinding::Array); mBuffer->onBindingChanged(context, false, BufferBinding::Array);
mBuffer.set(context, bufferIn); mBuffer.set(context, bufferIn);
if (mBuffer.get() && containerIsBound) if (mBuffer.get() && containerIsBound)
mBuffer->onBindingChanged(true, BufferBinding::Array); mBuffer->onBindingChanged(context, true, BufferBinding::Array);
} }
void VertexBinding::onContainerBindingChanged(bool bound) void VertexBinding::onContainerBindingChanged(const Context *context, bool bound)
{ {
if (mBuffer.get()) if (mBuffer.get())
mBuffer->onBindingChanged(bound, BufferBinding::Array); mBuffer->onBindingChanged(context, bound, BufferBinding::Array);
} }
void VertexBinding::updateCachedBufferSizeMinusOffset() void VertexBinding::updateCachedBufferSizeMinusOffset()
......
...@@ -38,7 +38,8 @@ class VertexBinding final : angle::NonCopyable ...@@ -38,7 +38,8 @@ class VertexBinding final : angle::NonCopyable
const BindingPointer<Buffer> &getBuffer() const { return mBuffer; } const BindingPointer<Buffer> &getBuffer() const { return mBuffer; }
void setBuffer(const gl::Context *context, Buffer *bufferIn, bool containerIsBound); void setBuffer(const gl::Context *context, Buffer *bufferIn, bool containerIsBound);
void onContainerBindingChanged(bool bound);
void onContainerBindingChanged(const Context *context, bool bound);
// Called from VertexArray. // Called from VertexArray.
void updateCachedBufferSizeMinusOffset(); void updateCachedBufferSizeMinusOffset();
......
...@@ -172,24 +172,10 @@ bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLi ...@@ -172,24 +172,10 @@ bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLi
} }
} }
// TODO(jmadill): Cache this. http://anglebug.com/1391 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
if (webglCompatibility)
{ {
for (size_t attributeIndex : activeAttribs) ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
{ return false;
const VertexAttribute &attrib = vertexAttribs[attributeIndex];
ASSERT(attrib.enabled);
const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
gl::Buffer *buffer = binding.getBuffer().get();
if (buffer && buffer->isBoundForTransformFeedbackAndOtherUse())
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(),
VertexBufferBoundForTransformFeedback);
return false;
}
}
} }
return true; return true;
......
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