Commit 407d4e77 by Geoff Lang Committed by Commit Bot

Perform ANGLE_instanced_arrays validation for WebGL contexts.

TEST=conformance2/rendering/instanced-arrays BUG=angleproject:1988 Change-Id: Ie513dcc7b1af540764fd5fe3790d3e6e3457f048 Reviewed-on: https://chromium-review.googlesource.com/475136Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent ff5c63ee
......@@ -1820,6 +1820,74 @@ bool ValidateES2CopyTexImageParameters(ValidationContext *context,
return (width > 0 && height > 0);
}
bool ValidateDrawElementsInstancedBase(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLsizei primcount,
IndexRange *indexRangeOut)
{
if (primcount < 0)
{
context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
return false;
}
if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
{
return false;
}
// No-op zero primitive count
return (primcount > 0);
}
bool ValidateDrawArraysInstancedBase(Context *context,
GLenum mode,
GLint first,
GLsizei count,
GLsizei primcount)
{
if (primcount < 0)
{
context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
return false;
}
if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
{
return false;
}
// No-op if zero primitive count
return (primcount > 0);
}
bool ValidateDrawInstancedANGLEAndWebGL(Context *context)
{
// Verify there is at least one active attribute with a divisor of zero
const State &state = context->getGLState();
Program *program = state.getProgram();
const auto &attribs = state.getVertexArray()->getVertexAttributes();
const auto &bindings = state.getVertexArray()->getVertexBindings();
for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
const VertexAttribute &attrib = attribs[attributeIndex];
const VertexBinding &binding = bindings[attrib.bindingIndex];
if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
{
return true;
}
}
context->handleError(
Error(GL_INVALID_OPERATION, "At least one attribute must have a divisor of zero."));
return false;
}
} // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target)
......@@ -3768,44 +3836,12 @@ bool ValidateDrawArraysInstanced(Context *context,
GLsizei count,
GLsizei primcount)
{
if (primcount < 0)
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
{
return false;
}
// No-op if zero primitive count
return (primcount > 0);
}
static bool ValidateDrawInstancedANGLE(Context *context)
{
// Verify there is at least one active attribute with a divisor of zero
const gl::State &state = context->getGLState();
gl::Program *program = state.getProgram();
const auto &attribs = state.getVertexArray()->getVertexAttributes();
const auto &bindings = state.getVertexArray()->getVertexBindings();
for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
const VertexAttribute &attrib = attribs[attributeIndex];
const VertexBinding &binding = bindings[attrib.bindingIndex];
if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
{
return true;
}
}
context->handleError(Error(GL_INVALID_OPERATION,
"ANGLE_instanced_arrays requires that at least one active attribute"
"has a divisor of zero."));
return false;
return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
}
bool ValidateDrawArraysInstancedANGLE(Context *context,
......@@ -3814,12 +3850,12 @@ bool ValidateDrawArraysInstancedANGLE(Context *context,
GLsizei count,
GLsizei primcount)
{
if (!ValidateDrawInstancedANGLE(context))
if (!ValidateDrawInstancedANGLEAndWebGL(context))
{
return false;
}
return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
}
bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
......@@ -4016,19 +4052,13 @@ bool ValidateDrawElementsInstanced(Context *context,
GLsizei primcount,
IndexRange *indexRangeOut)
{
if (primcount < 0)
if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
{
return false;
}
// No-op zero primitive count
return (primcount > 0);
return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
indexRangeOut);
}
bool ValidateDrawElementsInstancedANGLE(Context *context,
......@@ -4039,13 +4069,13 @@ bool ValidateDrawElementsInstancedANGLE(Context *context,
GLsizei primcount,
IndexRange *indexRangeOut)
{
if (!ValidateDrawInstancedANGLE(context))
if (!ValidateDrawInstancedANGLEAndWebGL(context))
{
return false;
}
return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
indexRangeOut);
return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
indexRangeOut);
}
bool ValidateFramebufferTextureBase(Context *context,
......
......@@ -683,9 +683,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
{
const std::string &vert =
"attribute float a_pos;\n"
"attribute float a_w;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
" gl_Position = vec4(a_pos, a_pos, a_pos, a_w);\n"
"}\n";
const std::string &frag =
......@@ -699,6 +700,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
ASSERT_NE(-1, posLocation);
GLint wLocation = glGetAttribLocation(program.get(), "a_w");
ASSERT_NE(-1, wLocation);
glUseProgram(program.get());
GLBuffer buffer;
......@@ -708,6 +713,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
glEnableVertexAttribArray(posLocation);
glVertexAttribDivisor(posLocation, 1);
glEnableVertexAttribArray(wLocation);
glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
glVertexAttribDivisor(wLocation, 0);
const uint8_t* zeroOffset = nullptr;
// Test touching the last element is valid.
......@@ -736,6 +745,46 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
ASSERT_GL_NO_ERROR();
}
// Test that at least one attribute has a zero divisor for WebGL
TEST_P(WebGL2CompatibilityTest, InstancedDrawZeroDivisor)
{
const std::string &vert =
"attribute float a_pos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(a_pos, a_pos, a_pos, 1.0);\n"
"}\n";
const std::string &frag =
"precision highp float;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
ANGLE_GL_PROGRAM(program, vert, frag);
GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
ASSERT_NE(-1, posLocation);
glUseProgram(program.get());
GLBuffer buffer;
glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
glBufferData(GL_ARRAY_BUFFER, 16, nullptr, GL_STATIC_DRAW);
glEnableVertexAttribArray(posLocation);
glVertexAttribDivisor(posLocation, 1);
// Test touching the last element is valid.
glVertexAttribPointer(0, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, nullptr);
glDrawArraysInstanced(GL_POINTS, 0, 1, 4);
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
glVertexAttribDivisor(posLocation, 0);
ASSERT_GL_NO_ERROR();
}
// Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
TEST_P(WebGLCompatibilityTest, NPOT)
{
......
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