Commit 6a5d98c4 by Jiawei Shao Committed by Commit Bot

ES31: Implement Vertex Attrib Binding on D3D11

This patch implements Vertex Attrib Binding on D3D11 and enables all the test cases related to Vertex Attrib Binding on D3D11 back-ends. On D3D11 back-ends the information in both GL vertex attributes and bindings should be updated together. When a binding is dirty, we need to find out and update all the attributes that are using this binding. To speed up this process, this patch adds a map from each binding to all the attrib indexes that are using this binding. This map may be updated when VertexAttribBinding is implicitly or explicitly called. With this map we can easily get all the attributes that should be updated with the current dirty binding. This patch also removes some unused variables in VertexArray11.cpp. BUG=angleproject:2700 TEST=dEQP-GLES31.functional.vertex_attribute_binding.* angle_end2end_tests Change-Id: I9a28ec357fd3aba835812cecc410cfa4e3734f0c Reviewed-on: https://chromium-review.googlesource.com/1048980 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c16f518e
...@@ -24,6 +24,7 @@ VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings) ...@@ -24,6 +24,7 @@ VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
for (size_t i = 0; i < maxAttribs; i++) for (size_t i = 0; i < maxAttribs; i++)
{ {
mVertexAttributes.emplace_back(static_cast<GLuint>(i)); mVertexAttributes.emplace_back(static_cast<GLuint>(i));
mBindingToAttributeMasks[i].set(i);
} }
} }
...@@ -41,6 +42,31 @@ bool VertexArrayState::hasEnabledNullPointerClientArray() const ...@@ -41,6 +42,31 @@ bool VertexArrayState::hasEnabledNullPointerClientArray() const
return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any(); return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
} }
AttributesMask VertexArrayState::getBindingToAttributeMasks(GLuint bindingIndex) const
{
ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
return mBindingToAttributeMasks[bindingIndex];
}
// Set an attribute using a new binding.
void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
{
ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
// Update the binding-attribute map.
const GLuint oldBindingIndex = mVertexAttributes[attribIndex].bindingIndex;
ASSERT(oldBindingIndex != newBindingIndex);
ASSERT(mBindingToAttributeMasks[oldBindingIndex].test(attribIndex) &&
!mBindingToAttributeMasks[newBindingIndex].test(attribIndex));
mBindingToAttributeMasks[oldBindingIndex].reset(attribIndex);
mBindingToAttributeMasks[newBindingIndex].set(attribIndex);
// Set the attribute using the new binding.
mVertexAttributes[attribIndex].bindingIndex = newBindingIndex;
}
// VertexArray implementation. // VertexArray implementation.
VertexArray::VertexArray(rx::GLImplFactory *factory, VertexArray::VertexArray(rx::GLImplFactory *factory,
GLuint id, GLuint id,
...@@ -185,11 +211,11 @@ void VertexArray::setVertexAttribBinding(const Context *context, ...@@ -185,11 +211,11 @@ void VertexArray::setVertexAttribBinding(const Context *context,
{ {
// In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable. // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
ASSERT(context->getClientVersion() >= ES_3_1); ASSERT(context->getClientVersion() >= ES_3_1);
mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
mState.setAttribBinding(attribIndex, bindingIndex);
setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING); setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
} }
mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
} }
void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor) void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
......
...@@ -63,12 +63,17 @@ class VertexArrayState final : angle::NonCopyable ...@@ -63,12 +63,17 @@ class VertexArrayState final : angle::NonCopyable
return mVertexAttributes[attribIndex].bindingIndex; return mVertexAttributes[attribIndex].bindingIndex;
} }
void setAttribBinding(size_t attribIndex, GLuint newBindingIndex);
// Combines mClientMemoryAttribsMask with mEnabledAttributesMask. // Combines mClientMemoryAttribsMask with mEnabledAttributesMask.
gl::AttributesMask getEnabledClientMemoryAttribsMask() const; gl::AttributesMask getEnabledClientMemoryAttribsMask() const;
// Extra validation performed on the Vertex Array. // Extra validation performed on the Vertex Array.
bool hasEnabledNullPointerClientArray() const; bool hasEnabledNullPointerClientArray() const;
// Get all the attributes in an AttributesMask that are using the given binding.
AttributesMask getBindingToAttributeMasks(GLuint bindingIndex) const;
private: private:
friend class VertexArray; friend class VertexArray;
std::string mLabel; std::string mLabel;
...@@ -84,6 +89,11 @@ class VertexArrayState final : angle::NonCopyable ...@@ -84,6 +89,11 @@ class VertexArrayState final : angle::NonCopyable
// attribs. // attribs.
gl::AttributesMask mClientMemoryAttribsMask; gl::AttributesMask mClientMemoryAttribsMask;
gl::AttributesMask mNullPointerClientMemoryAttribsMask; gl::AttributesMask mNullPointerClientMemoryAttribsMask;
// Records the mappings from each binding to all of the attributes that are using that binding.
// It is used to label all the relevant attributes dirty when we are updating a dirty binding in
// VertexArray11::syncStates().
std::array<AttributesMask, MAX_VERTEX_ATTRIB_BINDINGS> mBindingToAttributeMasks;
}; };
class VertexArray final : public angle::ObserverInterface, public LabeledObject class VertexArray final : public angle::ObserverInterface, public LabeledObject
......
...@@ -37,18 +37,25 @@ void VertexArray11::destroy(const gl::Context *context) ...@@ -37,18 +37,25 @@ void VertexArray11::destroy(const gl::Context *context)
{ {
} }
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \ // As VertexAttribPointer can modify both attribute and binding, we should also set other attributes
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \ // that are also using this binding dirty.
ASSERT(INDEX == mState.getBindingIndexFromAttribIndex(INDEX)); \ #define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
updateVertexAttribStorage(stateManager, dirtyBit, INDEX); \ case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
invalidateVertexBuffer = true; \ if (attribBits[INDEX][gl::VertexArray::DirtyAttribBitType::DIRTY_ATTRIB_POINTER]) \
{ \
attributesToUpdate |= mState.getBindingToAttributeMasks(INDEX); \
} \
else \
{ \
attributesToUpdate.set(INDEX); \
} \
invalidateVertexBuffer = true; \
break; break;
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \ #define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \ case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
ASSERT(INDEX == mState.getBindingIndexFromAttribIndex(INDEX)); \ attributesToUpdate |= mState.getBindingToAttributeMasks(INDEX); \
updateVertexAttribStorage(stateManager, dirtyBit, INDEX); \ invalidateVertexBuffer = true; \
invalidateVertexBuffer = true; \
break; break;
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \ #define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
...@@ -76,6 +83,8 @@ gl::Error VertexArray11::syncState(const gl::Context *context, ...@@ -76,6 +83,8 @@ gl::Error VertexArray11::syncState(const gl::Context *context,
bool invalidateVertexBuffer = false; bool invalidateVertexBuffer = false;
gl::AttributesMask attributesToUpdate;
// Make sure we trigger re-translation for static index or vertex data. // Make sure we trigger re-translation for static index or vertex data.
for (size_t dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
...@@ -101,6 +110,11 @@ gl::Error VertexArray11::syncState(const gl::Context *context, ...@@ -101,6 +110,11 @@ gl::Error VertexArray11::syncState(const gl::Context *context,
} }
} }
for (size_t attribIndex : attributesToUpdate)
{
updateVertexAttribStorage(stateManager, attribIndex);
}
if (invalidateVertexBuffer) if (invalidateVertexBuffer)
{ {
// TODO(jmadill): Individual attribute invalidation. // TODO(jmadill): Individual attribute invalidation.
...@@ -188,16 +202,10 @@ gl::Error VertexArray11::updateElementArrayStorage(const gl::Context *context, ...@@ -188,16 +202,10 @@ gl::Error VertexArray11::updateElementArrayStorage(const gl::Context *context,
ClassifyIndexStorage(context->getGLState(), mState.getElementArrayBuffer().get(), ClassifyIndexStorage(context->getGLState(), mState.getElementArrayBuffer().get(),
drawCallParams.type(), mCachedDestinationIndexType, offset); drawCallParams.type(), mCachedDestinationIndexType, offset);
// Mark non-static buffers as irrelevant.
bool isStatic = (mCurrentElementArrayStorage == IndexStorageType::Static);
mRelevantDirtyBitsMask.set(gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA, isStatic);
return gl::NoError(); return gl::NoError();
} }
void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager, void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager, size_t attribIndex)
size_t dirtyBit,
size_t attribIndex)
{ {
const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex); const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
const gl::VertexBinding &binding = mState.getBindingFromAttribIndex(attribIndex); const gl::VertexBinding &binding = mState.getBindingFromAttribIndex(attribIndex);
...@@ -213,10 +221,6 @@ void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager, ...@@ -213,10 +221,6 @@ void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager,
mAttributeStorageTypes[attribIndex] = newStorageType; mAttributeStorageTypes[attribIndex] = newStorageType;
mDynamicAttribsMask.set(attribIndex, newStorageType == VertexStorageType::DYNAMIC); mDynamicAttribsMask.set(attribIndex, newStorageType == VertexStorageType::DYNAMIC);
// Mark non-static buffers as irrelevant.
size_t bufferDataDirtyBit = (gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + attribIndex);
mRelevantDirtyBitsMask.set(bufferDataDirtyBit, newStorageType == VertexStorageType::STATIC);
if (newStorageType == VertexStorageType::CURRENT_VALUE) if (newStorageType == VertexStorageType::CURRENT_VALUE)
{ {
stateManager->invalidateCurrentValueAttrib(attribIndex); stateManager->invalidateCurrentValueAttrib(attribIndex);
......
...@@ -60,7 +60,6 @@ class VertexArray11 : public VertexArrayImpl ...@@ -60,7 +60,6 @@ class VertexArray11 : public VertexArrayImpl
private: private:
void updateVertexAttribStorage(StateManager11 *stateManager, void updateVertexAttribStorage(StateManager11 *stateManager,
size_t dirtyBit,
size_t attribIndex); size_t attribIndex);
gl::Error updateDirtyAttribs(const gl::Context *context, gl::Error updateDirtyAttribs(const gl::Context *context,
const gl::AttributesMask &activeDirtyAttribs); const gl::AttributesMask &activeDirtyAttribs);
...@@ -75,9 +74,6 @@ class VertexArray11 : public VertexArrayImpl ...@@ -75,9 +74,6 @@ class VertexArray11 : public VertexArrayImpl
// The mask of attributes marked as dynamic. // The mask of attributes marked as dynamic.
gl::AttributesMask mDynamicAttribsMask; gl::AttributesMask mDynamicAttribsMask;
// Mask applied to dirty bits on syncState. If a bit is on, it is relevant.
gl::VertexArray::DirtyBits mRelevantDirtyBitsMask;
// A set of attributes we know are dirty, and need to be re-translated. // A set of attributes we know are dirty, and need to be re-translated.
gl::AttributesMask mAttribsToTranslate; gl::AttributesMask mAttribsToTranslate;
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.array_size.vertex_fragment.default_block_struct_member = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.array_size.vertex_fragment.default_block_struct_member = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.name_length.vertex_fragment.default_block_struct_member = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.name_length.vertex_fragment.default_block_struct_member = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.type.vertex_fragment.struct.* = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.type.vertex_fragment.struct.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.texture.gather.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.texture.gather.* = SKIP
// TODO(xinghua.cao@intel.com): FAIL expectation instead of SKIP should be sufficient for OpenGL, but the // TODO(xinghua.cao@intel.com): FAIL expectation instead of SKIP should be sufficient for OpenGL, but the
......
...@@ -533,6 +533,4 @@ ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11()); ...@@ -533,6 +533,4 @@ ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11());
ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3()); ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3());
// TODO(jiawei.shao@intel.com): Add D3D11 when Vertex Attrib Binding is supported on D3D11 ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
// back-ends.
ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES());
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