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, ...@@ -1820,6 +1820,74 @@ bool ValidateES2CopyTexImageParameters(ValidationContext *context,
return (width > 0 && height > 0); 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 } // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target) bool ValidTextureTarget(const ValidationContext *context, GLenum target)
...@@ -3768,44 +3836,12 @@ bool ValidateDrawArraysInstanced(Context *context, ...@@ -3768,44 +3836,12 @@ bool ValidateDrawArraysInstanced(Context *context,
GLsizei count, GLsizei count,
GLsizei primcount) GLsizei primcount)
{ {
if (primcount < 0) if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
{
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
{ {
return false; return false;
} }
// No-op if zero primitive count return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
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;
} }
bool ValidateDrawArraysInstancedANGLE(Context *context, bool ValidateDrawArraysInstancedANGLE(Context *context,
...@@ -3814,12 +3850,12 @@ bool ValidateDrawArraysInstancedANGLE(Context *context, ...@@ -3814,12 +3850,12 @@ bool ValidateDrawArraysInstancedANGLE(Context *context,
GLsizei count, GLsizei count,
GLsizei primcount) GLsizei primcount)
{ {
if (!ValidateDrawInstancedANGLE(context)) if (!ValidateDrawInstancedANGLEAndWebGL(context))
{ {
return false; return false;
} }
return ValidateDrawArraysInstanced(context, mode, first, count, primcount); return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
} }
bool ValidateDrawElementsBase(ValidationContext *context, GLenum type) bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
...@@ -4016,19 +4052,13 @@ bool ValidateDrawElementsInstanced(Context *context, ...@@ -4016,19 +4052,13 @@ bool ValidateDrawElementsInstanced(Context *context,
GLsizei primcount, GLsizei primcount,
IndexRange *indexRangeOut) 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; return false;
} }
// No-op zero primitive count return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
return (primcount > 0); indexRangeOut);
} }
bool ValidateDrawElementsInstancedANGLE(Context *context, bool ValidateDrawElementsInstancedANGLE(Context *context,
...@@ -4039,12 +4069,12 @@ bool ValidateDrawElementsInstancedANGLE(Context *context, ...@@ -4039,12 +4069,12 @@ bool ValidateDrawElementsInstancedANGLE(Context *context,
GLsizei primcount, GLsizei primcount,
IndexRange *indexRangeOut) IndexRange *indexRangeOut)
{ {
if (!ValidateDrawInstancedANGLE(context)) if (!ValidateDrawInstancedANGLEAndWebGL(context))
{ {
return false; return false;
} }
return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
indexRangeOut); indexRangeOut);
} }
......
...@@ -683,9 +683,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced) ...@@ -683,9 +683,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
{ {
const std::string &vert = const std::string &vert =
"attribute float a_pos;\n" "attribute float a_pos;\n"
"attribute float a_w;\n"
"void main()\n" "void main()\n"
"{\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"; "}\n";
const std::string &frag = const std::string &frag =
...@@ -699,6 +700,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced) ...@@ -699,6 +700,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
GLint posLocation = glGetAttribLocation(program.get(), "a_pos"); GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
ASSERT_NE(-1, posLocation); ASSERT_NE(-1, posLocation);
GLint wLocation = glGetAttribLocation(program.get(), "a_w");
ASSERT_NE(-1, wLocation);
glUseProgram(program.get()); glUseProgram(program.get());
GLBuffer buffer; GLBuffer buffer;
...@@ -708,6 +713,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced) ...@@ -708,6 +713,10 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
glEnableVertexAttribArray(posLocation); glEnableVertexAttribArray(posLocation);
glVertexAttribDivisor(posLocation, 1); glVertexAttribDivisor(posLocation, 1);
glEnableVertexAttribArray(wLocation);
glVertexAttribPointer(wLocation, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
glVertexAttribDivisor(wLocation, 0);
const uint8_t* zeroOffset = nullptr; const uint8_t* zeroOffset = nullptr;
// Test touching the last element is valid. // Test touching the last element is valid.
...@@ -736,6 +745,46 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced) ...@@ -736,6 +745,46 @@ TEST_P(WebGL2CompatibilityTest, DrawArraysBufferOutOfBoundsInstanced)
ASSERT_GL_NO_ERROR(); 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 // Tests that NPOT is not enabled by default in WebGL 1 and that it can be enabled
TEST_P(WebGLCompatibilityTest, NPOT) 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