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)
for (size_t i = 0; i < maxAttribs; i++)
{
mVertexAttributes.emplace_back(static_cast<GLuint>(i));
mBindingToAttributeMasks[i].set(i);
}
}
......@@ -41,6 +42,31 @@ bool VertexArrayState::hasEnabledNullPointerClientArray() const
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::VertexArray(rx::GLImplFactory *factory,
GLuint id,
......@@ -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.
ASSERT(context->getClientVersion() >= ES_3_1);
mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
mState.setAttribBinding(attribIndex, bindingIndex);
setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
}
mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex);
}
void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
......
......@@ -63,12 +63,17 @@ class VertexArrayState final : angle::NonCopyable
return mVertexAttributes[attribIndex].bindingIndex;
}
void setAttribBinding(size_t attribIndex, GLuint newBindingIndex);
// Combines mClientMemoryAttribsMask with mEnabledAttributesMask.
gl::AttributesMask getEnabledClientMemoryAttribsMask() const;
// Extra validation performed on the Vertex Array.
bool hasEnabledNullPointerClientArray() const;
// Get all the attributes in an AttributesMask that are using the given binding.
AttributesMask getBindingToAttributeMasks(GLuint bindingIndex) const;
private:
friend class VertexArray;
std::string mLabel;
......@@ -84,6 +89,11 @@ class VertexArrayState final : angle::NonCopyable
// attribs.
gl::AttributesMask mClientMemoryAttribsMask;
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
......
......@@ -37,18 +37,25 @@ void VertexArray11::destroy(const gl::Context *context)
{
}
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
ASSERT(INDEX == mState.getBindingIndexFromAttribIndex(INDEX)); \
updateVertexAttribStorage(stateManager, dirtyBit, INDEX); \
invalidateVertexBuffer = true; \
// As VertexAttribPointer can modify both attribute and binding, we should also set other attributes
// that are also using this binding dirty.
#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
if (attribBits[INDEX][gl::VertexArray::DirtyAttribBitType::DIRTY_ATTRIB_POINTER]) \
{ \
attributesToUpdate |= mState.getBindingToAttributeMasks(INDEX); \
} \
else \
{ \
attributesToUpdate.set(INDEX); \
} \
invalidateVertexBuffer = true; \
break;
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
ASSERT(INDEX == mState.getBindingIndexFromAttribIndex(INDEX)); \
updateVertexAttribStorage(stateManager, dirtyBit, INDEX); \
invalidateVertexBuffer = true; \
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
attributesToUpdate |= mState.getBindingToAttributeMasks(INDEX); \
invalidateVertexBuffer = true; \
break;
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
......@@ -76,6 +83,8 @@ gl::Error VertexArray11::syncState(const gl::Context *context,
bool invalidateVertexBuffer = false;
gl::AttributesMask attributesToUpdate;
// Make sure we trigger re-translation for static index or vertex data.
for (size_t dirtyBit : dirtyBits)
{
......@@ -101,6 +110,11 @@ gl::Error VertexArray11::syncState(const gl::Context *context,
}
}
for (size_t attribIndex : attributesToUpdate)
{
updateVertexAttribStorage(stateManager, attribIndex);
}
if (invalidateVertexBuffer)
{
// TODO(jmadill): Individual attribute invalidation.
......@@ -188,16 +202,10 @@ gl::Error VertexArray11::updateElementArrayStorage(const gl::Context *context,
ClassifyIndexStorage(context->getGLState(), mState.getElementArrayBuffer().get(),
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();
}
void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager,
size_t dirtyBit,
size_t attribIndex)
void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager, size_t attribIndex)
{
const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
const gl::VertexBinding &binding = mState.getBindingFromAttribIndex(attribIndex);
......@@ -213,10 +221,6 @@ void VertexArray11::updateVertexAttribStorage(StateManager11 *stateManager,
mAttributeStorageTypes[attribIndex] = newStorageType;
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)
{
stateManager->invalidateCurrentValueAttrib(attribIndex);
......
......@@ -60,7 +60,6 @@ class VertexArray11 : public VertexArrayImpl
private:
void updateVertexAttribStorage(StateManager11 *stateManager,
size_t dirtyBit,
size_t attribIndex);
gl::Error updateDirtyAttribs(const gl::Context *context,
const gl::AttributesMask &activeDirtyAttribs);
......@@ -75,9 +74,6 @@ class VertexArray11 : public VertexArrayImpl
// The mask of attributes marked as dynamic.
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.
gl::AttributesMask mAttribsToTranslate;
......
......@@ -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.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 D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = 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
......
......@@ -533,6 +533,4 @@ ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11());
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
// back-ends.
ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES());
ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
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