Commit ac43aaa2 by Jamie Madill Committed by Commit Bot

Refactor client check from ValidateDrawAttribs.

This moves out some shared logic into a more accessible place. We don't need to validate buffer overflows when using robust resource access but we do need to validate we are using client side data correctly. Bug: angleproject:1391 Change-Id: I7a3dca8409c5a1faf1ff7bc732d5ed1bd62eb3b1 Reviewed-on: https://chromium-review.googlesource.com/1148817 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 8c1508bc
......@@ -451,7 +451,7 @@ void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingI
mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
}
bool VertexArray::hasTransformFeedbackBindingConflict(const AttributesMask &activeAttribues) const
bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
{
// Fast check first.
if (!mCachedTransformFeedbackConflictedBindingsMask.any())
......@@ -459,6 +459,8 @@ bool VertexArray::hasTransformFeedbackBindingConflict(const AttributesMask &acti
return false;
}
const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
// Slow check. We must ensure that the conflicting attributes are enabled/active.
for (size_t attribIndex : activeAttribues)
{
......
......@@ -249,7 +249,7 @@ class VertexArray final : public angle::ObserverInterface, public LabeledObject
AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; }
void onBindingChanged(const Context *context, bool bound);
bool hasTransformFeedbackBindingConflict(const AttributesMask &activeAttribues) const;
bool hasTransformFeedbackBindingConflict(const gl::Context *context) const;
private:
~VertexArray() override;
......
......@@ -79,32 +79,42 @@ bool DifferenceCanOverflow(GLint a, GLint b)
return !checkedA.IsValid();
}
bool ValidateDrawClientAttribs(Context *context)
{
if (!context->getStateCache().hasAnyEnabledClientAttrib())
return true;
const gl::State &state = context->getGLState();
if (context->getExtensions().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;
}
if (state.getVertexArray()->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;
}
return true;
}
bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
{
const gl::State &state = context->getGLState();
const gl::Program *program = state.getProgram();
const VertexArray *vao = state.getVertexArray();
bool webglCompatibility = context->getExtensions().webglCompatibility;
if (context->getStateCache().hasAnyEnabledClientAttrib())
if (!ValidateDrawClientAttribs(context))
{
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;
}
return false;
}
// If we're drawing zero vertices, we have enough data.
......@@ -113,6 +123,7 @@ bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLi
return true;
}
const VertexArray *vao = state.getVertexArray();
const auto &vertexAttribs = vao->getVertexAttributes();
const auto &vertexBindings = vao->getVertexBindings();
......@@ -170,12 +181,6 @@ bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLi
}
}
if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
return false;
}
return true;
}
......@@ -2873,6 +2878,17 @@ bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
{
return false;
}
if (count > 0)
{
const VertexArray *vao = context->getGLState().getVertexArray();
if (vao->hasTransformFeedbackBindingConflict(context))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(),
VertexBufferBoundForTransformFeedback);
return false;
}
}
}
}
......@@ -3135,20 +3151,10 @@ bool ValidateDrawElementsCommon(Context *context,
}
}
if (context->getExtensions().robustBufferAccessBehavior)
{
// Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
// access is enabled.
if (!ValidateDrawAttribs(context, primcount, 0, 1))
{
return false;
}
}
else if (count == 0)
if (context->getExtensions().robustBufferAccessBehavior || count == 0)
{
// ValidateDrawAttribs also does some extra validation that is independent of the vertex
// count.
if (!ValidateDrawAttribs(context, 0, 0, 0))
// Special checks are needed for client attribs. But we don't need to validate overflows.
if (!ValidateDrawClientAttribs(context))
{
return false;
}
......
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