Commit df682a8e by Shao Committed by Commit Bot

ES31: Refactor syncState in VertexArrayGL

This patch intends to solve several design issues by refactoring the process of syncState in VertexArrayGL before implementing ES3.1 feature Vertex Attrib Binding on the OpenGL back-end. 1. Use nullptr as the flag of using client memory pointer 2. Simplify comparisons in updateAttribPointer. 3. Put all code related to mFunctions->vertexAttrib*Pointer() into an individual function 4. Remove redundant mStateManager->bindVertexArray() in all update* functioins and only call it once in syncState(). BUG=angleproject:1593 Change-Id: I8f68534bb9291a601b9b77954d7281e5171c2b55 Reviewed-on: https://chromium-review.googlesource.com/465378 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 9676d1af
...@@ -168,7 +168,7 @@ class VertexArray final : public LabeledObject ...@@ -168,7 +168,7 @@ class VertexArray final : public LabeledObject
DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN, DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
}; };
typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits; using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
static size_t GetAttribIndex(size_t dirtyBit); static size_t GetAttribIndex(size_t dirtyBit);
......
...@@ -53,11 +53,6 @@ struct VertexAttribute final : private angle::NonCopyable ...@@ -53,11 +53,6 @@ struct VertexAttribute final : private angle::NonCopyable
GLuint bindingIndex; GLuint bindingIndex;
}; };
bool operator==(const VertexAttribute &a, const VertexAttribute &b);
bool operator!=(const VertexAttribute &a, const VertexAttribute &b);
bool operator==(const VertexBinding &a, const VertexBinding &b);
bool operator!=(const VertexBinding &a, const VertexBinding &b);
size_t ComputeVertexAttributeTypeSize(const VertexAttribute &attrib); size_t ComputeVertexAttributeTypeSize(const VertexAttribute &attrib);
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. // Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
......
...@@ -9,37 +9,6 @@ ...@@ -9,37 +9,6 @@
namespace gl namespace gl
{ {
inline bool operator==(const VertexBinding &a, const VertexBinding &b)
{
return a.stride == b.stride &&
a.divisor == b.divisor &&
a.offset == b.offset &&
a.buffer.get() == b.buffer.get();
}
inline bool operator!=(const VertexBinding &a, const VertexBinding &b)
{
return !(a == b);
}
inline bool operator==(const VertexAttribute &a, const VertexAttribute &b)
{
return a.enabled == b.enabled &&
a.type == b.type &&
a.size == b.size &&
a.normalized == b.normalized &&
a.pureInteger == b.pureInteger &&
a.pointer == b.pointer &&
a.relativeOffset == b.relativeOffset &&
a.vertexAttribArrayStride == b.vertexAttribArrayStride &&
a.bindingIndex == b.bindingIndex;
}
inline bool operator!=(const VertexAttribute &a, const VertexAttribute &b)
{
return !(a == b);
}
inline VertexAttribCurrentValueData::VertexAttribCurrentValueData() inline VertexAttribCurrentValueData::VertexAttribCurrentValueData()
: Type(GL_FLOAT) : Type(GL_FLOAT)
{ {
......
...@@ -31,6 +31,22 @@ bool AttributeNeedsStreaming(const VertexAttribute &attrib, const VertexBinding ...@@ -31,6 +31,22 @@ bool AttributeNeedsStreaming(const VertexAttribute &attrib, const VertexBinding
{ {
return (attrib.enabled && binding.buffer.get() == nullptr); return (attrib.enabled && binding.buffer.get() == nullptr);
} }
bool SameVertexAttribFormat(const VertexAttribute &a, const VertexAttribute &b)
{
return a.size == b.size && a.type == b.type && a.normalized == b.normalized &&
a.pureInteger == b.pureInteger && a.relativeOffset == b.relativeOffset;
}
bool SameVertexBuffer(const VertexBinding &a, const VertexBinding &b)
{
return a.stride == b.stride && a.offset == b.offset && a.buffer.get() == b.buffer.get();
}
bool IsVertexAttribPointerSupported(size_t attribIndex, const VertexAttribute &attrib)
{
return (attribIndex == attrib.bindingIndex && attrib.relativeOffset == 0);
}
} // anonymous namespace } // anonymous namespace
VertexArrayGL::VertexArrayGL(const VertexArrayState &state, VertexArrayGL::VertexArrayGL(const VertexArrayState &state,
...@@ -368,25 +384,11 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib ...@@ -368,25 +384,11 @@ gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttrib
// Compute where the 0-index vertex would be. // Compute where the 0-index vertex would be.
const size_t vertexStartOffset = curBufferOffset - (firstIndex * destStride); const size_t vertexStartOffset = curBufferOffset - (firstIndex * destStride);
if (attrib.pureInteger) callVertexAttribPointer(static_cast<GLuint>(idx), attrib,
{ static_cast<GLsizei>(destStride),
ASSERT(!attrib.normalized); static_cast<GLintptr>(vertexStartOffset));
mFunctions->vertexAttribIPointer(static_cast<GLuint>(idx), attrib.size, attrib.type,
static_cast<GLsizei>(destStride),
reinterpret_cast<const void *>(vertexStartOffset));
}
else
{
mFunctions->vertexAttribPointer(static_cast<GLuint>(idx), attrib.size, attrib.type,
attrib.normalized, static_cast<GLsizei>(destStride),
reinterpret_cast<const void *>(vertexStartOffset));
}
curBufferOffset += destStride * streamedVertexCount; curBufferOffset += destStride * streamedVertexCount;
// Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
// need to be streamed later, there is no chance that the caching will skip it.
mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
} }
unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER); unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
...@@ -424,16 +426,15 @@ void VertexArrayGL::updateNeedsStreaming(size_t attribIndex) ...@@ -424,16 +426,15 @@ void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
void VertexArrayGL::updateAttribEnabled(size_t attribIndex) void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
{ {
const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex); const bool enabled = mData.getVertexAttribute(attribIndex).enabled;
if (mAppliedAttributes[attribIndex].enabled == attrib.enabled) if (mAppliedAttributes[attribIndex].enabled == enabled)
{ {
return; return;
} }
updateNeedsStreaming(attribIndex); updateNeedsStreaming(attribIndex);
mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); if (enabled)
if (attrib.enabled)
{ {
mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex)); mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
} }
...@@ -441,18 +442,26 @@ void VertexArrayGL::updateAttribEnabled(size_t attribIndex) ...@@ -441,18 +442,26 @@ void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
{ {
mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex)); mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
} }
mAppliedAttributes[attribIndex].enabled = attrib.enabled;
mAppliedAttributes[attribIndex].enabled = enabled;
} }
void VertexArrayGL::updateAttribPointer(size_t attribIndex) void VertexArrayGL::updateAttribPointer(size_t attribIndex)
{ {
const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex); const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
ASSERT(attribIndex == attrib.bindingIndex);
GLuint bindingIndex = attrib.bindingIndex; // TODO(jiawei.shao@intel.com): Vertex Attrib Binding
ASSERT(IsVertexAttribPointerSupported(attribIndex, attrib));
const GLuint bindingIndex = attrib.bindingIndex;
const VertexBinding &binding = mData.getVertexBinding(bindingIndex); const VertexBinding &binding = mData.getVertexBinding(bindingIndex);
if (mAppliedAttributes[attribIndex] == attrib && mAppliedBindings[bindingIndex] == binding) // We do not need to compare attrib.pointer because when we use a different client memory
// pointer, we don't need to update mAttributesNeedStreaming by binding.buffer and we won't
// update attribPointer in this function.
if (SameVertexAttribFormat(mAppliedAttributes[attribIndex], attrib) &&
mAppliedAttributes[attribIndex].bindingIndex == bindingIndex &&
SameVertexBuffer(mAppliedBindings[attribIndex], binding))
{ {
return; return;
} }
...@@ -460,75 +469,82 @@ void VertexArrayGL::updateAttribPointer(size_t attribIndex) ...@@ -460,75 +469,82 @@ void VertexArrayGL::updateAttribPointer(size_t attribIndex)
updateNeedsStreaming(attribIndex); updateNeedsStreaming(attribIndex);
// If we need to stream, defer the attribPointer to the draw call. // If we need to stream, defer the attribPointer to the draw call.
if (mAttributesNeedStreaming[attribIndex])
{
return;
}
// Skip the attribute that is disabled and uses a client memory pointer. // Skip the attribute that is disabled and uses a client memory pointer.
const Buffer *arrayBuffer = binding.buffer.get(); const Buffer *arrayBuffer = binding.buffer.get();
if (arrayBuffer == nullptr) if (arrayBuffer == nullptr)
{ {
ASSERT(!attrib.enabled); // Mark the applied binding is using a client memory pointer by setting its buffer to
// nullptr so that if it doesn't use a client memory pointer later, there is no chance that
// Mark the applied attribute as dirty by setting an invalid size so that if it doesn't // the caching will skip it.
// use a client memory pointer later, there is no chance that the caching will skip it. mAppliedBindings[bindingIndex].buffer.set(nullptr);
mAppliedAttributes[attribIndex].size = static_cast<GLuint>(-1);
return; return;
} }
mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
// Since ANGLE always uses a non-zero VAO, we cannot use a client memory pointer on it: // Since ANGLE always uses a non-zero VAO, we cannot use a client memory pointer on it:
// [OpenGL ES 3.0.2] Section 2.8 page 24: // [OpenGL ES 3.0.2] Section 2.8 page 24:
// An INVALID_OPERATION error is generated when a non-zero vertex array object is bound, // An INVALID_OPERATION error is generated when a non-zero vertex array object is bound,
// zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument // zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument
// is not NULL. // is not NULL.
ASSERT(arrayBuffer != nullptr);
const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer); const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID()); mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
const void *inputPointer =
reinterpret_cast<const uint8_t *>(binding.offset + attrib.relativeOffset);
if (attrib.pureInteger) callVertexAttribPointer(static_cast<GLuint>(attribIndex), attrib, binding.stride,
{ binding.offset);
mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
binding.stride, inputPointer);
}
else
{
mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
attrib.normalized, binding.stride, inputPointer);
}
mAppliedAttributes[attribIndex].size = attrib.size; mAppliedAttributes[attribIndex].size = attrib.size;
mAppliedAttributes[attribIndex].type = attrib.type; mAppliedAttributes[attribIndex].type = attrib.type;
mAppliedAttributes[attribIndex].normalized = attrib.normalized; mAppliedAttributes[attribIndex].normalized = attrib.normalized;
mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger; mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger;
mAppliedAttributes[attribIndex].pointer = attrib.pointer;
mAppliedAttributes[attribIndex].relativeOffset = attrib.relativeOffset; mAppliedAttributes[attribIndex].relativeOffset = attrib.relativeOffset;
mAppliedAttributes[attribIndex].vertexAttribArrayStride = attrib.vertexAttribArrayStride;
mAppliedAttributes[attribIndex].bindingIndex = bindingIndex;
mAppliedBindings[bindingIndex].stride = binding.stride; mAppliedBindings[bindingIndex].stride = binding.stride;
mAppliedBindings[bindingIndex].offset = binding.offset; mAppliedBindings[bindingIndex].offset = binding.offset;
mAppliedBindings[bindingIndex].buffer = binding.buffer; mAppliedBindings[bindingIndex].buffer = binding.buffer;
} }
void VertexArrayGL::callVertexAttribPointer(GLuint attribIndex,
const VertexAttribute &attrib,
GLsizei stride,
GLintptr offset) const
{
const GLvoid *pointer = reinterpret_cast<const GLvoid *>(offset);
if (attrib.pureInteger)
{
ASSERT(!attrib.normalized);
mFunctions->vertexAttribIPointer(attribIndex, attrib.size, attrib.type, stride, pointer);
}
else
{
mFunctions->vertexAttribPointer(attribIndex, attrib.size, attrib.type, attrib.normalized,
stride, pointer);
}
}
void VertexArrayGL::updateAttribDivisor(size_t attribIndex) void VertexArrayGL::updateAttribDivisor(size_t attribIndex)
{ {
ASSERT(attribIndex == mData.getBindingIndexFromAttribIndex(attribIndex)); const GLuint bindingIndex = mData.getVertexAttribute(attribIndex).bindingIndex;
ASSERT(attribIndex == bindingIndex);
const VertexBinding &binding = mData.getVertexBinding(attribIndex); const GLuint divisor = mData.getVertexBinding(bindingIndex).divisor;
if (mAppliedBindings[attribIndex].divisor != binding.divisor) if (mAppliedAttributes[attribIndex].bindingIndex == bindingIndex &&
mAppliedBindings[bindingIndex].divisor == divisor)
{ {
mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); return;
mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), binding.divisor);
mAppliedBindings[attribIndex].divisor = binding.divisor;
} }
mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), divisor);
mAppliedAttributes[attribIndex].bindingIndex = bindingIndex;
mAppliedBindings[bindingIndex].divisor = divisor;
} }
void VertexArrayGL::syncState(ContextImpl *contextImpl, const VertexArray::DirtyBits &dirtyBits) void VertexArrayGL::syncState(ContextImpl *contextImpl, const VertexArray::DirtyBits &dirtyBits)
{ {
mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
for (size_t dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
......
...@@ -80,6 +80,11 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -80,6 +80,11 @@ class VertexArrayGL : public VertexArrayImpl
void updateAttribPointer(size_t attribIndex); void updateAttribPointer(size_t attribIndex);
void updateAttribDivisor(size_t attribIndex); void updateAttribDivisor(size_t attribIndex);
void callVertexAttribPointer(GLuint attribIndex,
const gl::VertexAttribute &attrib,
GLsizei stride,
GLintptr offset) const;
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
StateManagerGL *mStateManager; StateManagerGL *mStateManager;
......
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