Commit 9ab5b822 by Geoff Lang Committed by Commit Bot

Validate that vertex shader input matches the vertex attribute types.

BUG=angleproject:2012 TEST=conformance2/rendering/attrib-type-match Change-Id: Ic282e0933a5c3c377322dd484534fcc1dfcb3840 Reviewed-on: https://chromium-review.googlesource.com/517974 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent b7d5e303
...@@ -132,4 +132,31 @@ size_t ComputeVertexBindingElementCount(const VertexBinding &binding, ...@@ -132,4 +132,31 @@ size_t ComputeVertexBindingElementCount(const VertexBinding &binding,
return drawCount; return drawCount;
} }
GLenum GetVertexAttributeBaseType(const VertexAttribute &attrib)
{
if (attrib.pureInteger)
{
switch (attrib.type)
{
case GL_BYTE:
case GL_SHORT:
case GL_INT:
return GL_INT;
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT:
case GL_UNSIGNED_INT:
return GL_UNSIGNED_INT;
default:
UNREACHABLE();
return GL_NONE;
}
}
else
{
return GL_FLOAT;
}
}
} // namespace gl } // namespace gl
...@@ -65,6 +65,8 @@ size_t ComputeVertexBindingElementCount(const VertexBinding &binding, ...@@ -65,6 +65,8 @@ size_t ComputeVertexBindingElementCount(const VertexBinding &binding,
size_t drawCount, size_t drawCount,
size_t instanceCount); size_t instanceCount);
GLenum GetVertexAttributeBaseType(const VertexAttribute &attrib);
struct VertexAttribCurrentValueData struct VertexAttribCurrentValueData
{ {
union { union {
......
...@@ -740,6 +740,32 @@ bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context) ...@@ -740,6 +740,32 @@ bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
return true; return true;
} }
bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
{
const Program *program = context->getGLState().getProgram();
const VertexArray *vao = context->getGLState().getVertexArray();
for (const auto &shaderAttribute : program->getAttributes())
{
GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
const auto &currentValue =
context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
{
context->handleError(Error(
GL_INVALID_OPERATION,
"Vertex shader input type does not match the type of the bound vertex attribute."));
return false;
}
}
return true;
}
} // anonymous namespace } // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target) bool ValidTextureTarget(const ValidationContext *context, GLenum target)
...@@ -2747,6 +2773,12 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count) ...@@ -2747,6 +2773,12 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
return false; return false;
} }
// Detect that the vertex shader input types match the attribute types
if (!ValidateVertexShaderAttributeTypeMatch(context))
{
return false;
}
// Detect that the color buffer types match the fragment shader output types // Detect that the color buffer types match the fragment shader output types
if (!ValidateFragmentShaderColorBufferTypeMatch(context)) if (!ValidateFragmentShaderColorBufferTypeMatch(context))
{ {
......
...@@ -2497,6 +2497,70 @@ TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch) ...@@ -2497,6 +2497,70 @@ TEST_P(WebGL2CompatibilityTest, FragmentShaderColorBufferTypeMissmatch)
EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_ERROR(GL_INVALID_OPERATION);
} }
// Verify that errors are generated when the vertex shader intput doesn't match the bound attribute
// types
TEST_P(WebGL2CompatibilityTest, VertexShaderAttributeTypeMissmatch)
{
const std::string vertexShader =
"#version 300 es\n"
"in vec4 floatInput;\n"
"in uvec4 uintInput;\n"
"in ivec4 intInput;\n"
"void main() {\n"
" gl_Position = vec4(floatInput.x, uintInput.x, intInput.x, 1);\n"
"}\n";
const std::string fragmentShader =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 outputColor;\n"
"void main() {\n"
" outputColor = vec4(0, 0, 0, 1);"
"}\n";
ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
glUseProgram(program.get());
GLint floatLocation = glGetAttribLocation(program, "floatInput");
GLint uintLocation = glGetAttribLocation(program, "uintInput");
GLint intLocation = glGetAttribLocation(program, "intInput");
// Default attributes are of float types
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Set the default attributes to the correct types, should succeed
glVertexAttribI4ui(uintLocation, 0, 0, 0, 1);
glVertexAttribI4i(intLocation, 0, 0, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_NO_ERROR();
// Change the default float attribute to an integer, should fail
glVertexAttribI4ui(floatLocation, 0, 0, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Use a buffer for some attributes
GLBuffer buffer;
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
glEnableVertexAttribArray(floatLocation);
glVertexAttribPointer(floatLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_NO_ERROR();
// Use a float pointer attrib for a uint input
glEnableVertexAttribArray(uintLocation);
glVertexAttribPointer(uintLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Use a uint pointer for the uint input
glVertexAttribIPointer(uintLocation, 4, GL_UNSIGNED_INT, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest, ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
......
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