Commit 0131ff40 by Olli Etuaho Committed by Commit Bot

Fix using a large vertex attrib divisor on D3D11

A divisor >= 256 used to trigger an assert on the D3D11 backend since it couldn't fit into the input layout cache. Increase the space reserved for the divisor in the input layout cache to make sure that the correct input layout will get used and to fix the assert. BUG=angleproject:2832 TEST=angle_end2end_tests Change-Id: I34eead6c4e8c4fea379bbafc8670b4e32a5b633b Reviewed-on: https://chromium-review.googlesource.com/1236293Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent e25b8006
...@@ -59,7 +59,8 @@ struct PackedAttribute ...@@ -59,7 +59,8 @@ struct PackedAttribute
uint8_t attribType; uint8_t attribType;
uint8_t semanticIndex; uint8_t semanticIndex;
uint8_t vertexFormatType; uint8_t vertexFormatType;
uint8_t divisor; uint8_t dummyPadding;
uint32_t divisor;
}; };
} // anonymous namespace } // anonymous namespace
...@@ -81,17 +82,18 @@ void PackedAttributeLayout::addAttributeData(GLenum glType, ...@@ -81,17 +82,18 @@ void PackedAttributeLayout::addAttributeData(GLenum glType,
packedAttrib.attribType = static_cast<uint8_t>(attribType); packedAttrib.attribType = static_cast<uint8_t>(attribType);
packedAttrib.semanticIndex = static_cast<uint8_t>(semanticIndex); packedAttrib.semanticIndex = static_cast<uint8_t>(semanticIndex);
packedAttrib.vertexFormatType = static_cast<uint8_t>(vertexFormatType); packedAttrib.vertexFormatType = static_cast<uint8_t>(vertexFormatType);
packedAttrib.divisor = static_cast<uint8_t>(divisor); packedAttrib.dummyPadding = 0u;
packedAttrib.divisor = static_cast<uint32_t>(divisor);
ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType); ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType);
ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex); ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex);
ASSERT(static_cast<gl::VertexFormatType>(packedAttrib.vertexFormatType) == vertexFormatType); ASSERT(static_cast<gl::VertexFormatType>(packedAttrib.vertexFormatType) == vertexFormatType);
ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor); ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor);
static_assert(sizeof(uint32_t) == sizeof(PackedAttribute), static_assert(sizeof(uint64_t) == sizeof(PackedAttribute),
"PackedAttributes must be 32-bits exactly."); "PackedAttributes must be 64-bits exactly.");
attributeData[numAttributes++] = gl::bitCast<uint32_t>(packedAttrib); attributeData[numAttributes++] = gl::bitCast<uint64_t>(packedAttrib);
} }
bool PackedAttributeLayout::operator==(const PackedAttributeLayout &other) const bool PackedAttributeLayout::operator==(const PackedAttributeLayout &other) const
......
...@@ -48,7 +48,7 @@ struct PackedAttributeLayout ...@@ -48,7 +48,7 @@ struct PackedAttributeLayout
uint32_t numAttributes; uint32_t numAttributes;
uint32_t flags; uint32_t flags;
gl::AttribArray<uint32_t> attributeData; gl::AttribArray<uint64_t> attributeData;
}; };
} // namespace rx } // namespace rx
......
...@@ -419,6 +419,12 @@ TEST_P(InstancingTestPoints, DrawElements) ...@@ -419,6 +419,12 @@ TEST_P(InstancingTestPoints, DrawElements)
checkQuads(); checkQuads();
} }
class InstancingTestES3 : public InstancingTest
{
public:
InstancingTestES3() {}
};
class InstancingTestES31 : public InstancingTest class InstancingTestES31 : public InstancingTest
{ {
public: public:
...@@ -517,6 +523,104 @@ TEST_P(InstancingTestES31, UpdateAttribBindingByVertexAttribDivisor) ...@@ -517,6 +523,104 @@ TEST_P(InstancingTestES31, UpdateAttribBindingByVertexAttribDivisor)
glDeleteVertexArrays(1, &vao); glDeleteVertexArrays(1, &vao);
} }
// Verify that a large divisor that also changes doesn't cause issues and renders correctly.
TEST_P(InstancingTestES3, LargeDivisor)
{
const std::string &vs = R"(#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec4 a_color;
out vec4 v_color;
void main()
{
gl_Position = a_position;
gl_PointSize = 4.0f;
v_color = a_color;
})";
const std::string &fs = R"(#version 300 es
precision highp float;
in vec4 v_color;
out vec4 my_FragColor;
void main()
{
my_FragColor = v_color;
})";
ANGLE_GL_PROGRAM(program, vs, fs);
glUseProgram(program);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GLBuffer buf;
glBindBuffer(GL_ARRAY_BUFFER, buf);
std::vector<GLfloat> vertices;
for (size_t i = 0u; i < 4u; ++i)
{
vertices.push_back(0.0f + i * 0.25f);
vertices.push_back(0.0f);
vertices.push_back(0.0f);
vertices.push_back(1.0f);
}
glBufferData(GL_ARRAY_BUFFER, vertices.size() * 4u, vertices.data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
ASSERT_GL_NO_ERROR();
GLBuffer colorBuf;
glBindBuffer(GL_ARRAY_BUFFER, colorBuf);
std::array<GLColor, 4> ubyteColors = {GLColor::red, GLColor::green};
std::vector<float> floatColors;
for (const GLColor &color : ubyteColors)
{
floatColors.push_back(color.R / 255.0f);
floatColors.push_back(color.G / 255.0f);
floatColors.push_back(color.B / 255.0f);
floatColors.push_back(color.A / 255.0f);
}
glBufferData(GL_ARRAY_BUFFER, floatColors.size() * 4u, floatColors.data(), GL_DYNAMIC_DRAW);
const GLuint kColorDivisor = 65536u * 2u;
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, nullptr);
glVertexAttribDivisor(1, kColorDivisor);
std::array<GLuint, 1u> indices = {0u};
std::array<GLuint, 3u> divisorsToTry = {256u, 65536u, 65536u * 2u};
for (GLuint divisorToTry : divisorsToTry)
{
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribDivisor(0, divisorToTry);
GLuint instanceCount = divisorToTry + 1u;
unsigned int pointsRendered = (instanceCount - 1u) / divisorToTry + 1u;
glDrawElementsInstanced(GL_POINTS, indices.size(), GL_UNSIGNED_INT, indices.data(),
instanceCount);
ASSERT_GL_NO_ERROR();
// Check that the intended number of points has been rendered.
for (unsigned int pointIndex = 0u; pointIndex < pointsRendered + 1u; ++pointIndex)
{
GLint pointx = static_cast<GLint>((pointIndex * 0.125f + 0.5f) * getWindowWidth());
GLint pointy = static_cast<GLint>(0.5f * getWindowHeight());
if (pointIndex < pointsRendered)
{
GLuint pointColorIndex = (pointIndex * divisorToTry) / kColorDivisor;
EXPECT_PIXEL_COLOR_EQ(pointx, pointy, ubyteColors[pointColorIndex]);
}
else
{
// Clear color.
EXPECT_PIXEL_COLOR_EQ(pointx, pointy, GLColor::blue);
}
}
}
}
// 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. We test on D3D9 and D3D11 9_3 because they use special codepaths // tests should be run against. We test on D3D9 and D3D11 9_3 because they use special codepaths
// when attribute zero is instanced, unlike D3D11. // when attribute zero is instanced, unlike D3D11.
...@@ -533,4 +637,6 @@ ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11()); ...@@ -533,4 +637,6 @@ ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11());
ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3()); ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3());
ANGLE_INSTANTIATE_TEST(InstancingTestES3, ES3_OPENGL(), ES3_OPENGLES(), ES3_D3D11());
ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11()); ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
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