Commit 2c0d6a94 by Jamie Madill Committed by Commit Bot

WebGL: Fix DrawElements test and remove size check.

Also optimizes the DrawElements validation to remove redundant tests. Also make some more validation WebGL-specific. Bug: angleproject:2979 Change-Id: I2d5c3094ed86ebadbc572e46b8ae105431f7ae68 Reviewed-on: https://chromium-review.googlesource.com/c/1343139Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 5829c03d
...@@ -221,7 +221,6 @@ MSG kLightParameterOutOfRange = "Light parameter out of range."; ...@@ -221,7 +221,6 @@ MSG kLightParameterOutOfRange = "Light parameter out of range.";
MSG kMaterialParameterOutOfRange = "Material parameter out of range."; MSG kMaterialParameterOutOfRange = "Material parameter out of range.";
MSG kMatrixStackOverflow = "Current matrix stack is full."; MSG kMatrixStackOverflow = "Current matrix stack is full.";
MSG kMatrixStackUnderflow = "Current matrix stack has only a single matrix."; MSG kMatrixStackUnderflow = "Current matrix stack has only a single matrix.";
MSG kMismatchedByteCountType = "Buffer size does not align with data type.";
MSG kMismatchedFormat = "Format must match internal format."; MSG kMismatchedFormat = "Format must match internal format.";
MSG kMismatchedTargetAndFormat = "Invalid texture target and format combination."; MSG kMismatchedTargetAndFormat = "Invalid texture target and format combination.";
MSG kMismatchedTypeAndFormat = "Invalid format and type combination."; MSG kMismatchedTypeAndFormat = "Invalid format and type combination.";
......
...@@ -3030,10 +3030,10 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3030,10 +3030,10 @@ bool ValidateDrawElementsCommon(Context *context,
Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
GLuint typeBytes = GetTypeInfo(type).bytes; GLuint typeBytes = GetTypeInfo(type).bytes;
ASSERT(isPow2(typeBytes) && typeBytes > 0);
if (context->getExtensions().webglCompatibility) if (context->getExtensions().webglCompatibility)
{ {
ASSERT(isPow2(typeBytes) && typeBytes > 0);
if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0) if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
{ {
// [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
...@@ -3051,38 +3051,57 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3051,38 +3051,57 @@ bool ValidateDrawElementsCommon(Context *context,
context->validationError(GL_INVALID_VALUE, kNegativeOffset); context->validationError(GL_INVALID_VALUE, kNegativeOffset);
return false; return false;
} }
if (!elementArrayBuffer)
{
// [WebGL 1.0] Section 6.2 No Client Side Arrays
// If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
// the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
return false;
}
if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
{
context->validationError(GL_INVALID_OPERATION,
kElementArrayBufferBoundForTransformFeedback);
return false;
}
} }
else if (elementArrayBuffer && elementArrayBuffer->isMapped()) else
{
if (elementArrayBuffer)
{
if (elementArrayBuffer->isMapped())
{ {
// WebGL buffers cannot be mapped/unmapped because the MapBufferRange, // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
// FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API. // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14 // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
context->validationError(GL_INVALID_OPERATION, "Index buffer is mapped."); context->validationError(GL_INVALID_OPERATION, "Index buffer is mapped.");
return false; return false;
} }
}
if (context->getExtensions().webglCompatibility || else if (!context->getGLState().areClientArraysEnabled())
!context->getGLState().areClientArraysEnabled())
{
if (!elementArrayBuffer)
{ {
// [WebGL 1.0] Section 6.2 No Client Side Arrays
// If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
// the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding); context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
return false; return false;
} }
} }
if (count > 0 && !elementArrayBuffer && !indices) if (count > 0)
{
if (!elementArrayBuffer)
{ {
// This is an application error that would normally result in a crash, but we catch it and if (!indices)
// return an error {
context->validationError(GL_INVALID_OPERATION, "No element array buffer and no pointer."); // This is an application error that would normally result in a crash, but we catch
// it and return an error
context->validationError(GL_INVALID_OPERATION,
"No element array buffer and no pointer.");
return false; return false;
} }
}
if (count > 0 && elementArrayBuffer) else
{ {
// The max possible type size is 8 and count is on 32 bits so doing the multiplication // The max possible type size is 8 and count is on 32 bits so doing the multiplication
// in a 64 bit integer is safe. Also we are guaranteed that here count > 0. // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
...@@ -3113,32 +3132,17 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3113,32 +3132,17 @@ bool ValidateDrawElementsCommon(Context *context,
context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize); context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
return false; return false;
} }
ASSERT(isPow2(typeSize) && typeSize > 0);
if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
{
context->validationError(GL_INVALID_OPERATION, kMismatchedByteCountType);
return false;
}
if (context->getExtensions().webglCompatibility &&
elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
{
context->validationError(GL_INVALID_OPERATION,
kElementArrayBufferBoundForTransformFeedback);
return false;
}
} }
if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0) if (!context->getExtensions().robustBufferAccessBehavior && primcount > 0)
{ {
// Use the parameter buffer to retrieve and cache the index range. // Use the parameter buffer to retrieve and cache the index range.
IndexRange indexRange; IndexRange indexRange;
ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange)); ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
// If we use an index greater than our maximum supported index range, return an error. // If we use an index greater than our maximum supported index range, return an error.
// The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
// return an error if possible here. // always return an error if possible here.
if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex) if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
{ {
context->validationError(GL_INVALID_OPERATION, kExceedsMaxElement); context->validationError(GL_INVALID_OPERATION, kExceedsMaxElement);
...@@ -3153,6 +3157,7 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3153,6 +3157,7 @@ bool ValidateDrawElementsCommon(Context *context,
// No op if there are no real indices in the index data (all are primitive restart). // No op if there are no real indices in the index data (all are primitive restart).
return (indexRange.vertexIndexCount > 0); return (indexRange.vertexIndexCount > 0);
} }
}
return true; return true;
} }
......
...@@ -64,6 +64,12 @@ class DrawElementsTest : public ANGLETest ...@@ -64,6 +64,12 @@ class DrawElementsTest : public ANGLETest
GLuint mProgram; GLuint mProgram;
}; };
class WebGLDrawElementsTest : public DrawElementsTest
{
public:
WebGLDrawElementsTest() { setWebGLCompatibilityEnabled(true); }
};
// Test no error is generated when using client-side arrays, indices = nullptr and count = 0 // Test no error is generated when using client-side arrays, indices = nullptr and count = 0
TEST_P(DrawElementsTest, ClientSideNullptrArrayZeroCount) TEST_P(DrawElementsTest, ClientSideNullptrArrayZeroCount)
{ {
...@@ -260,7 +266,7 @@ TEST_P(DrawElementsTest, DeletingAfterStreamingIndexes) ...@@ -260,7 +266,7 @@ TEST_P(DrawElementsTest, DeletingAfterStreamingIndexes)
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
// Test that the offset in the index buffer is forced to be a multiple of the element size // Test that the offset in the index buffer is forced to be a multiple of the element size
TEST_P(DrawElementsTest, DrawElementsTypeAlignment) TEST_P(WebGLDrawElementsTest, DrawElementsTypeAlignment)
{ {
const std::string &vert = const std::string &vert =
"attribute vec3 a_pos;\n" "attribute vec3 a_pos;\n"
...@@ -297,7 +303,7 @@ TEST_P(DrawElementsTest, DrawElementsTypeAlignment) ...@@ -297,7 +303,7 @@ TEST_P(DrawElementsTest, DrawElementsTypeAlignment)
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, zeroIndices);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
const GLubyte indices2[] = {0, 0, 0, 0, 0}; const GLushort indices2[] = {0, 0, 0, 0, 0, 0};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
...@@ -306,4 +312,5 @@ TEST_P(DrawElementsTest, DrawElementsTypeAlignment) ...@@ -306,4 +312,5 @@ TEST_P(DrawElementsTest, DrawElementsTypeAlignment)
} }
ANGLE_INSTANTIATE_TEST(DrawElementsTest, ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(DrawElementsTest, ES3_OPENGL(), ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(WebGLDrawElementsTest, ES2_OPENGL(), ES2_OPENGLES());
} // namespace } // namespace
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