From e858cb1db3c266f67adf998dc14bb17eccec084b Mon Sep 17 00:00:00 2001 From: Jamie Madill Date: Tue, 27 Mar 2018 09:44:32 -0400 Subject: [PATCH] Split VAO dirty bits to speed iteration. Using > 64 bits (we had over 90) would use a much slower dirty bit iteration. Speed this up by splitting the dirty bits into two levels. The first top level only has a single dirty bit per attrib, per binding, and one bit for the element array buffer. The next level has separate dirty bits for attribs and bindings. The D3D11 back-end doesn't actually care about individual dirty bits of attribs or bindings, since it resets entire attributes at a time, but the GL back-end only refreshes the necessary info. Improves the score of a simple state change microbenchmark by 15% on the D3D11 and GL back-ends with a no-op driver. Real-world impact will be smaller. Also includes a test suppression for an NVIDIA bug that surfaced when we changed the order of that GL commands were sent to the driver. BUG=angleproject:2389 Change-Id: If8d5e5eb0b27e2a77e20535e33626183d372d311 Reviewed-on: https://chromium-review.googlesource.com/556799 Reviewed-by: Geoff Lang Reviewed-by: Yuly Novikov Commit-Queue: Jamie Madill --- src/libANGLE/VertexArray.cpp | 39 ++++-- src/libANGLE/VertexArray.h | 63 ++++++---- src/libANGLE/VertexArray_unittest.cpp | 26 +--- src/libANGLE/renderer/VertexArrayImpl.h | 7 +- .../renderer/d3d/d3d11/VertexArray11.cpp | 4 +- .../renderer/d3d/d3d11/VertexArray11.h | 4 +- src/libANGLE/renderer/d3d/d3d9/VertexArray9.h | 10 +- src/libANGLE/renderer/gl/VertexArrayGL.cpp | 119 ++++++++++++------ src/libANGLE/renderer/gl/VertexArrayGL.h | 11 +- .../renderer/vulkan/VertexArrayVk.cpp | 4 +- src/libANGLE/renderer/vulkan/VertexArrayVk.h | 4 +- .../deqp_gles31_test_expectations.txt | 3 + 12 files changed, 192 insertions(+), 102 deletions(-) diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp index d738065dbb52a..10137743d25f8 100644 --- a/src/libANGLE/VertexArray.cpp +++ b/src/libANGLE/VertexArray.cpp @@ -111,7 +111,19 @@ size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit) static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS, "The stride of vertex attributes should equal to that of vertex bindings."); ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER); - return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS; + return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS; +} + +void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit) +{ + mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex); + mDirtyAttribBits[attribIndex].set(dirtyAttribBit); +} + +void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit) +{ + mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex); + mDirtyBindingBits[bindingIndex].set(dirtyBindingBit); } void VertexArray::bindVertexBufferImpl(const Context *context, @@ -137,8 +149,7 @@ void VertexArray::bindVertexBuffer(const Context *context, GLsizei stride) { bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride); - - mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex); + setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER); } void VertexArray::setVertexAttribBinding(const Context *context, @@ -153,8 +164,9 @@ void VertexArray::setVertexAttribBinding(const Context *context, ASSERT(context->getClientVersion() >= ES_3_1); mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex; - mDirtyBits.set(DIRTY_BIT_ATTRIB_0_BINDING + attribIndex); + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING); } + mState.mVertexAttributes[attribIndex].bindingIndex = static_cast(bindingIndex); } void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor) @@ -162,8 +174,7 @@ void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor) ASSERT(bindingIndex < getMaxBindings()); mState.mVertexBindings[bindingIndex].setDivisor(divisor); - - mDirtyBits.set(DIRTY_BIT_BINDING_0_DIVISOR + bindingIndex); + setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR); } void VertexArray::setVertexAttribFormatImpl(size_t attribIndex, @@ -194,8 +205,7 @@ void VertexArray::setVertexAttribFormat(size_t attribIndex, GLuint relativeOffset) { setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset); - - mDirtyBits.set(DIRTY_BIT_ATTRIB_0_FORMAT + attribIndex); + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT); } void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor) @@ -214,7 +224,7 @@ void VertexArray::enableAttribute(size_t attribIndex, bool enabledState) mState.mVertexAttributesTypeMask.setIndex( GetVertexAttributeBaseType(mState.mVertexAttributes[attribIndex]), attribIndex); - mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attribIndex); + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED); // Update state cache mState.mEnabledAttributesMask.set(attribIndex, enabledState); @@ -246,7 +256,7 @@ void VertexArray::setVertexAttribPointer(const Context *context, bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride); - mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex); + setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER); } void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer) @@ -264,8 +274,15 @@ void VertexArray::syncState(const Context *context) { if (mDirtyBits.any()) { - mVertexArray->syncState(context, mDirtyBits); + mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits); mDirtyBits.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 + // individual attribs. We could also look into schemes where iterating the dirty + // bit set also resets it as you pass through it. + memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits)); + memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits)); } } diff --git a/src/libANGLE/VertexArray.h b/src/libANGLE/VertexArray.h index 10b53c577d3cf..c5d57881e8ba5 100644 --- a/src/libANGLE/VertexArray.h +++ b/src/libANGLE/VertexArray.h @@ -153,40 +153,54 @@ class VertexArray final : public LabeledObject return mState.getEnabledAttributesMask(); } + // Dirty bits for VertexArrays use a heirarchical design. At the top level, each attribute + // has a single dirty bit. Then an array of MAX_ATTRIBS dirty bits each has a dirty bit for + // enabled/pointer/format/binding. Bindings are handled similarly. Note that because the + // total number of dirty bits is 33, it will not be as fast on a 32-bit machine, which + // can't support the advanced 64-bit scanning intrinsics. We could consider packing the + // binding and attribute bits together if this becomes a problem. enum DirtyBitType { DIRTY_BIT_ELEMENT_ARRAY_BUFFER, - // Reserve bits for enabled flags - DIRTY_BIT_ATTRIB_0_ENABLED, - DIRTY_BIT_ATTRIB_MAX_ENABLED = DIRTY_BIT_ATTRIB_0_ENABLED + gl::MAX_VERTEX_ATTRIBS, + // Dirty bits for attributes. + DIRTY_BIT_ATTRIB_0, + DIRTY_BIT_ATTRIB_MAX = DIRTY_BIT_ATTRIB_0 + gl::MAX_VERTEX_ATTRIBS, - // Reserve bits for attrib pointers - DIRTY_BIT_ATTRIB_0_POINTER = DIRTY_BIT_ATTRIB_MAX_ENABLED, - DIRTY_BIT_ATTRIB_MAX_POINTER = DIRTY_BIT_ATTRIB_0_POINTER + gl::MAX_VERTEX_ATTRIBS, + // Dirty bits for bindings. + DIRTY_BIT_BINDING_0 = DIRTY_BIT_ATTRIB_MAX, + DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS, - // Reserve bits for changes to VertexAttribFormat - DIRTY_BIT_ATTRIB_0_FORMAT = DIRTY_BIT_ATTRIB_MAX_POINTER, - DIRTY_BIT_ATTRIB_MAX_FORMAT = DIRTY_BIT_ATTRIB_0_FORMAT + gl::MAX_VERTEX_ATTRIBS, - - // Reserve bits for changes to VertexAttribBinding - DIRTY_BIT_ATTRIB_0_BINDING = DIRTY_BIT_ATTRIB_MAX_FORMAT, - DIRTY_BIT_ATTRIB_MAX_BINDING = DIRTY_BIT_ATTRIB_0_BINDING + gl::MAX_VERTEX_ATTRIBS, + DIRTY_BIT_UNKNOWN = DIRTY_BIT_BINDING_MAX, + DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN, + }; - // Reserve bits for changes to BindVertexBuffer - DIRTY_BIT_BINDING_0_BUFFER = DIRTY_BIT_ATTRIB_MAX_BINDING, - DIRTY_BIT_BINDING_MAX_BUFFER = DIRTY_BIT_BINDING_0_BUFFER + gl::MAX_VERTEX_ATTRIB_BINDINGS, + // We want to keep the number of dirty bits within 64 to keep iteration times fast. + static_assert(DIRTY_BIT_MAX <= 64, "Too many vertex array dirty bits."); - // Reserve bits for binding divisors - DIRTY_BIT_BINDING_0_DIVISOR = DIRTY_BIT_BINDING_MAX_BUFFER, - DIRTY_BIT_BINDING_MAX_DIVISOR = - DIRTY_BIT_BINDING_0_DIVISOR + gl::MAX_VERTEX_ATTRIB_BINDINGS, + enum DirtyAttribBitType + { + DIRTY_ATTRIB_ENABLED, + DIRTY_ATTRIB_POINTER, + DIRTY_ATTRIB_FORMAT, + DIRTY_ATTRIB_BINDING, + DIRTY_ATTRIB_UNKNOWN, + DIRTY_ATTRIB_MAX = DIRTY_ATTRIB_UNKNOWN, + }; - DIRTY_BIT_UNKNOWN = DIRTY_BIT_BINDING_MAX_DIVISOR, - DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN, + enum DirtyBindingBitType + { + DIRTY_BINDING_BUFFER, + DIRTY_BINDING_DIVISOR, + DIRTY_BINDING_UNKNOWN, + DIRTY_BINDING_MAX = DIRTY_BINDING_UNKNOWN, }; using DirtyBits = angle::BitSet; + using DirtyAttribBits = angle::BitSet; + using DirtyBindingBits = angle::BitSet; + using DirtyAttribBitsArray = std::array; + using DirtyBindingBitsArray = std::array; static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit); @@ -201,10 +215,15 @@ class VertexArray final : public LabeledObject private: ~VertexArray() override; + void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit); + void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit); + GLuint mId; VertexArrayState mState; DirtyBits mDirtyBits; + DirtyAttribBitsArray mDirtyAttribBits; + DirtyBindingBitsArray mDirtyBindingBits; rx::VertexArrayImpl *mVertexArray; }; diff --git a/src/libANGLE/VertexArray_unittest.cpp b/src/libANGLE/VertexArray_unittest.cpp index bf210b6b9cb53..4b22a30ef7519 100644 --- a/src/libANGLE/VertexArray_unittest.cpp +++ b/src/libANGLE/VertexArray_unittest.cpp @@ -19,7 +19,7 @@ using namespace gl; TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit) { VertexArray::DirtyBits dirtyBits; - constexpr size_t bits[] = {1, 4, 9, 16, 25, 36, 49, 64, 81, 92}; + constexpr size_t bits[] = {1, 4, 9, 16, 25}; constexpr GLint count = sizeof(bits) / sizeof(size_t); for (GLint i = 0; i < count; i++) { @@ -29,29 +29,13 @@ TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit) for (size_t dirtyBit : dirtyBits) { const size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); - if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED) + if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX) { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED, index); + EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0, index); } - else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER) + else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX) { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_POINTER, index); - } - else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_FORMAT) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_FORMAT, index); - } - else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_BINDING) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_BINDING, index); - } - else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_BUFFER) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0_BUFFER, index); - } - else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_DIVISOR) - { - EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0_DIVISOR, index); + EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0, index); } else ASSERT_TRUE(false); diff --git a/src/libANGLE/renderer/VertexArrayImpl.h b/src/libANGLE/renderer/VertexArrayImpl.h index e48cc53d6c69e..76728f9aeeec7 100644 --- a/src/libANGLE/renderer/VertexArrayImpl.h +++ b/src/libANGLE/renderer/VertexArrayImpl.h @@ -21,7 +21,10 @@ class VertexArrayImpl : angle::NonCopyable { public: VertexArrayImpl(const gl::VertexArrayState &state) : mState(state) {} - virtual void syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits) + virtual void syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) { } @@ -32,6 +35,6 @@ class VertexArrayImpl : angle::NonCopyable const gl::VertexArrayState &mState; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp index 7b707f9311fa9..0fd7fb6992528 100644 --- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp @@ -57,7 +57,9 @@ void VertexArray11::destroy(const gl::Context *context) } void VertexArray11::syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) { ASSERT(dirtyBits.any()); diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h index 663a18d971cca..435b014e83e94 100644 --- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h +++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -27,7 +27,9 @@ class VertexArray11 : public angle::ObserverInterface, public VertexArrayImpl void destroy(const gl::Context *context) override; void syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) override; + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override; // This will flush any pending attrib updates and then check the dynamic attribs mask. bool hasActiveDynamicAttrib(const gl::Context *context); gl::Error updateDirtyAndDynamicAttribs(const gl::Context *context, diff --git a/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h index 0f4410b8ded74..fe597be49fd86 100644 --- a/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h +++ b/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -24,7 +24,9 @@ class VertexArray9 : public VertexArrayImpl VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {} void syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) override; + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override; ~VertexArray9() override {} @@ -35,12 +37,14 @@ class VertexArray9 : public VertexArrayImpl }; inline void VertexArray9::syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) { ASSERT(dirtyBits.any()); Renderer9 *renderer = GetImplAs(context)->getRenderer(); mCurrentStateSerial = renderer->generateSerial(); } -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp index 09eccf43ce655..74967330f7bae 100644 --- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp +++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp @@ -640,56 +640,99 @@ void VertexArrayGL::updateBindingDivisor(size_t bindingIndex) mAppliedBindings[bindingIndex].setDivisor(adjustedDivisor); } -void VertexArrayGL::syncState(const gl::Context *context, const VertexArray::DirtyBits &dirtyBits) +void VertexArrayGL::syncDirtyAttrib(const gl::Context *context, + size_t attribIndex, + const gl::VertexArray::DirtyAttribBits &dirtyAttribBits) { - mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); + ASSERT(dirtyAttribBits.any()); - for (size_t dirtyBit : dirtyBits) + for (size_t dirtyBit : dirtyAttribBits) { - if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) + switch (dirtyBit) { - updateElementArrayBufferBinding(context); - continue; + case VertexArray::DIRTY_ATTRIB_ENABLED: + updateAttribEnabled(attribIndex); + break; + + case VertexArray::DIRTY_ATTRIB_POINTER: + updateAttribPointer(context, attribIndex); + break; + + case VertexArray::DIRTY_ATTRIB_FORMAT: + ASSERT(supportVertexAttribBinding()); + updateAttribFormat(attribIndex); + break; + + case VertexArray::DIRTY_ATTRIB_BINDING: + ASSERT(supportVertexAttribBinding()); + updateAttribBinding(attribIndex); + break; + + default: + UNREACHABLE(); + break; } + } +} - size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); - if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED && - dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED) - { - updateAttribEnabled(index); - } - else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER && - dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER) - { - updateAttribPointer(context, index); - } +void VertexArrayGL::syncDirtyBinding(const gl::Context *context, + size_t bindingIndex, + const gl::VertexArray::DirtyBindingBits &dirtyBindingBits) +{ + ASSERT(dirtyBindingBits.any()); - else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_FORMAT && - dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_FORMAT) - { - ASSERT(supportVertexAttribBinding()); - updateAttribFormat(index); - } - else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_BINDING && - dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_BINDING) - { - ASSERT(supportVertexAttribBinding()); - updateAttribBinding(index); - } - else if (dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0_BUFFER && - dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_BUFFER) + for (size_t dirtyBit : dirtyBindingBits) + { + switch (dirtyBit) { - ASSERT(supportVertexAttribBinding()); - updateBindingBuffer(context, index); + case VertexArray::DIRTY_BINDING_BUFFER: + ASSERT(supportVertexAttribBinding()); + updateBindingBuffer(context, bindingIndex); + break; + + case VertexArray::DIRTY_BINDING_DIVISOR: + updateBindingDivisor(bindingIndex); + break; + + default: + UNREACHABLE(); + break; } + } +} + +void VertexArrayGL::syncState(const gl::Context *context, + const VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) +{ + mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); - else if (dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0_DIVISOR && - dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_DIVISOR) + for (size_t dirtyBit : dirtyBits) + { + switch (dirtyBit) { - updateBindingDivisor(index); + case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER: + updateElementArrayBufferBinding(context); + break; + + default: + { + ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0); + size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); + if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX) + { + syncDirtyAttrib(context, index, attribBits[index]); + } + else + { + ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0 && + dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX); + syncDirtyBinding(context, index, bindingBits[index]); + } + break; + } } - else - UNREACHABLE(); } } diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/libANGLE/renderer/gl/VertexArrayGL.h index 5af5128d7b76c..d7dd00259f0ab 100644 --- a/src/libANGLE/renderer/gl/VertexArrayGL.h +++ b/src/libANGLE/renderer/gl/VertexArrayGL.h @@ -45,7 +45,10 @@ class VertexArrayGL : public VertexArrayImpl GLuint getAppliedElementArrayBufferID() const; void syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) override; + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override; + void applyNumViewsToDivisor(int numViews); private: @@ -81,6 +84,12 @@ class VertexArrayGL : public VertexArrayImpl gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask, GLsizei instanceCount, const gl::IndexRange &indexRange) const; + void syncDirtyAttrib(const gl::Context *context, + size_t attribIndex, + const gl::VertexArray::DirtyAttribBits &dirtyAttribBits); + void syncDirtyBinding(const gl::Context *context, + size_t bindingIndex, + const gl::VertexArray::DirtyBindingBits &dirtyBindingBits); void updateNeedsStreaming(size_t attribIndex); void updateAttribEnabled(size_t attribIndex); diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp index be79380eb994d..5e9a7796348b4 100644 --- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp +++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp @@ -94,7 +94,9 @@ gl::Error VertexArrayVk::streamVertexData(ContextVk *context, } void VertexArrayVk::syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) { ASSERT(dirtyBits.any()); diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h index a66f3c144d67a..48e88366e1e16 100644 --- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h +++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h @@ -32,7 +32,9 @@ class VertexArrayVk : public VertexArrayImpl size_t firstVertex, size_t lastVertex); void syncState(const gl::Context *context, - const gl::VertexArray::DirtyBits &dirtyBits) override; + const gl::VertexArray::DirtyBits &dirtyBits, + const gl::VertexArray::DirtyAttribBitsArray &attribBits, + const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override; const gl::AttribArray &getCurrentArrayBufferHandles() const; const gl::AttribArray &getCurrentArrayBufferOffsets() const; diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_test_expectations.txt index 44c3930f40a77..6101bb22ae612 100644 --- a/src/tests/deqp_support/deqp_gles31_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles31_test_expectations.txt @@ -1603,6 +1603,9 @@ 2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.random.nested_structs* = FAIL 2272 WIN NVIDIA OPENGL : dEQP-GLES31.functional.ssbo.layout.random.all* = FAIL +// An NVIDIA bug seems to occur when sending GL commands in a certain order to the driver +2432 NVIDIA OPENGL : dEQP-GLES31.functional.vertex_attribute_binding.usage.mixed_usage.mixed_api_change_binding_point = SKIP + // OpenGL and D3D11 Failing Tests 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.opaque_type_indexing.* = FAIL 1442 OPENGL D3D11 : dEQP-GLES31.functional.shaders.helper_invocation.* = FAIL