Commit 51af38b8 by Jamie Madill Committed by Commit Bot

Optimize ValidateDrawAttribs: Part 1.

This moves several loop checks outside the loop, and uses more of the gl::AttributesMask class to do bitset operations instead of using checks and for loops. Bug: angleproject:1391 Change-Id: I90a1a7db550390ecd1402cf5a8a6677fd852b7b0 Reviewed-on: https://chromium-review.googlesource.com/1008273Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent a7be1f77
......@@ -36,6 +36,11 @@ gl::AttributesMask VertexArrayState::getEnabledClientMemoryAttribsMask() const
return (mClientMemoryAttribsMask & mEnabledAttributesMask);
}
bool VertexArrayState::hasEnabledNullPointerClientArray() const
{
return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
}
// VertexArray implementation.
VertexArray::VertexArray(rx::GLImplFactory *factory,
GLuint id,
......@@ -272,6 +277,8 @@ void VertexArray::setVertexAttribPointer(const Context *context,
setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
mState.mClientMemoryAttribsMask.set(attribIndex, boundBuffer == nullptr);
mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
boundBuffer == nullptr && pointer == nullptr);
}
void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
......
......@@ -66,6 +66,9 @@ class VertexArrayState final : angle::NonCopyable
// Combines mClientMemoryAttribsMask with mEnabledAttributesMask.
gl::AttributesMask getEnabledClientMemoryAttribsMask() const;
// Extra validation performed on the Vertex Array.
bool hasEnabledNullPointerClientArray() const;
private:
friend class VertexArray;
std::string mLabel;
......@@ -80,6 +83,7 @@ class VertexArrayState final : angle::NonCopyable
// state is ignored. Thus we don't have to worry about binding state when using client memory
// attribs.
gl::AttributesMask mClientMemoryAttribsMask;
gl::AttributesMask mNullPointerClientMemoryAttribsMask;
};
class VertexArray final : public angle::ObserverInterface, public LabeledObject
......@@ -163,6 +167,16 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject
return mState.getEnabledAttributesMask();
}
gl::AttributesMask getEnabledClientMemoryAttribsMask() const
{
return mState.getEnabledClientMemoryAttribsMask();
}
bool hasEnabledNullPointerClientArray() const
{
return mState.hasEnabledNullPointerClientArray();
}
// Observer implementation
void onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
......
......@@ -75,57 +75,54 @@ bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLi
bool webglCompatibility = context->getExtensions().webglCompatibility;
const VertexArray *vao = state.getVertexArray();
const VertexArray *vao = state.getVertexArray();
const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
if (clientAttribs.any())
{
if (webglCompatibility || !state.areClientArraysEnabled())
{
// [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
// If a vertex attribute is enabled as an array via enableVertexAttribArray but no
// buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
// to drawArrays or drawElements will generate an INVALID_OPERATION error.
ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
return false;
}
else if (vao->hasEnabledNullPointerClientArray())
{
// This is an application error that would normally result in a crash, but we catch it
// and return an error
ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
return false;
}
}
// If we're drawing zero vertices, we have enough data.
if (vertexCount <= 0 || primcount <= 0)
{
return true;
}
const auto &vertexAttribs = vao->getVertexAttributes();
const auto &vertexBindings = vao->getVertexBindings();
for (size_t attributeIndex : vao->getEnabledAttributesMask())
const AttributesMask &activeAttribs =
(program->getActiveAttribLocationsMask() & vao->getEnabledAttributesMask());
for (size_t attributeIndex : activeAttribs)
{
const VertexAttribute &attrib = vertexAttribs[attributeIndex];
ASSERT(attrib.enabled);
// No need to range check for disabled attribs.
if (!attrib.enabled)
{
continue;
}
// If we have no buffer, then we either get an error, or there are no more checks to be
// done.
const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
gl::Buffer *buffer = binding.getBuffer().get();
if (!buffer)
{
if (webglCompatibility || !state.areClientArraysEnabled())
{
// [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
// If a vertex attribute is enabled as an array via enableVertexAttribArray but
// no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
// then calls to drawArrays or drawElements will generate an INVALID_OPERATION
// error.
ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
return false;
}
else if (attrib.pointer == nullptr)
{
// This is an application error that would normally result in a crash,
// but we catch it and return an error
ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
return false;
}
continue;
}
// This needs to come after the check for client arrays as even unused attributes cannot use
// client-side arrays
if (!program->isAttribLocationActive(attributeIndex))
{
continue;
}
// If we're drawing zero vertices, we have enough data.
if (vertexCount <= 0 || primcount <= 0)
{
continue;
}
ASSERT(program->isAttribLocationActive(attributeIndex));
GLint maxVertexElement = 0;
GLuint divisor = binding.getDivisor();
......
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