Commit b5560486 by shrekshao Committed by Commit Bot

BaseInstance VertexAttribDivisor fix

Add tests not using gl_InstanceID/gl_BaseInstance but set vertexAttribDivisor which implicitly reference base instance value. Add fixes and workarounds based on this change. Bug: chromium:891861, angleproject:3402 Change-Id: I2d93c181029f4ca1741f244363568096964d6b19 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1779350 Commit-Queue: Shrek Shao <shrekshao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 3a2e01ed
...@@ -268,7 +268,7 @@ angle::Result Context11::drawArrays(const gl::Context *context, ...@@ -268,7 +268,7 @@ angle::Result Context11::drawArrays(const gl::Context *context,
ASSERT(count > 0); ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(
context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0)); context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0));
return mRenderer->drawArrays(context, mode, first, count, 0); return mRenderer->drawArrays(context, mode, first, count, 0, 0);
} }
angle::Result Context11::drawArraysInstanced(const gl::Context *context, angle::Result Context11::drawArraysInstanced(const gl::Context *context,
...@@ -280,7 +280,7 @@ angle::Result Context11::drawArraysInstanced(const gl::Context *context, ...@@ -280,7 +280,7 @@ angle::Result Context11::drawArraysInstanced(const gl::Context *context,
ASSERT(count > 0); ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState( ANGLE_TRY(mRenderer->getStateManager()->updateState(
context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0)); context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0));
return mRenderer->drawArrays(context, mode, first, count, instanceCount); return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0);
} }
angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context, angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context,
...@@ -290,7 +290,10 @@ angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *cont ...@@ -290,7 +290,10 @@ angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instanceCount, GLsizei instanceCount,
GLuint baseInstance) GLuint baseInstance)
{ {
return drawArraysInstanced(context, mode, first, count, instanceCount); ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState(
context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0));
return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance);
} }
ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context, ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context,
...@@ -380,7 +383,8 @@ angle::Result Context11::drawArraysIndirect(const gl::Context *context, ...@@ -380,7 +383,8 @@ angle::Result Context11::drawArraysIndirect(const gl::Context *context,
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count, ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count,
gl::DrawElementsType::InvalidEnum, gl::DrawElementsType::InvalidEnum,
nullptr, cmd->instanceCount, 0)); nullptr, cmd->instanceCount, 0));
return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount); return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
cmd->baseInstance);
} }
else else
{ {
......
...@@ -1476,7 +1476,8 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, ...@@ -1476,7 +1476,8 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
GLsizei vertexCount, GLsizei vertexCount,
GLsizei instanceCount) GLsizei instanceCount,
GLuint baseInstance)
{ {
if (mStateManager.getCullEverything()) if (mStateManager.getCullEverything())
{ {
...@@ -1520,7 +1521,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, ...@@ -1520,7 +1521,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
if (adjustedInstanceCount == 0) if (adjustedInstanceCount == 0)
{ {
mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, 0); mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1534,7 +1535,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, ...@@ -1534,7 +1535,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
{ {
ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation( ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(
context, firstVertex, i)); context, firstVertex, i));
mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, 0); mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
} }
// This required by updateVertexOffsets... above but is outside of the loop for // This required by updateVertexOffsets... above but is outside of the loop for
...@@ -1554,7 +1555,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context, ...@@ -1554,7 +1555,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
} }
else else
{ {
mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, 0); mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, baseInstance);
} }
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -410,7 +410,8 @@ class Renderer11 : public RendererD3D ...@@ -410,7 +410,8 @@ class Renderer11 : public RendererD3D
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint firstVertex, GLint firstVertex,
GLsizei vertexCount, GLsizei vertexCount,
GLsizei instanceCount); GLsizei instanceCount,
GLuint baseInstance);
angle::Result drawElements(const gl::Context *context, angle::Result drawElements(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint startVertex, GLint startVertex,
......
...@@ -294,6 +294,82 @@ angle::Result ContextGL::drawArraysInstanced(const gl::Context *context, ...@@ -294,6 +294,82 @@ angle::Result ContextGL::drawArraysInstanced(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
gl::AttributesMask ContextGL::updateAttributesForBaseInstance(const gl::Program *program,
GLuint baseInstance)
{
gl::AttributesMask attribToUpdateMask;
if (baseInstance != 0)
{
const FunctionsGL *functions = getFunctions();
const auto &attribs = mState.getVertexArray()->getVertexAttributes();
const auto &bindings = mState.getVertexArray()->getVertexBindings();
for (GLuint attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++)
{
const gl::VertexAttribute &attrib = attribs[attribIndex];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
if (program->isAttribLocationActive(attribIndex) && binding.getDivisor() != 0)
{
attribToUpdateMask.set(attribIndex);
const char *p = static_cast<const char *>(attrib.pointer);
const size_t sourceStride = gl::ComputeVertexAttributeStride(attrib, binding);
const void *newPointer = p + sourceStride * baseInstance;
const BufferGL *buffer = GetImplAs<BufferGL>(binding.getBuffer().get());
// We often stream data from scratch buffers when client side data is being used
// and that information is in VertexArrayGL.
// Assert that the buffer is non-null because this case isn't handled.
ASSERT(buffer);
getStateManager()->bindBuffer(gl::BufferBinding::Array, buffer->getBufferID());
if (attrib.format->isPureInt())
{
functions->vertexAttribIPointer(attribIndex, attrib.format->channelCount,
gl::ToGLenum(attrib.format->vertexAttribType),
attrib.vertexAttribArrayStride, newPointer);
}
else
{
functions->vertexAttribPointer(attribIndex, attrib.format->channelCount,
gl::ToGLenum(attrib.format->vertexAttribType),
attrib.format->isNorm(),
attrib.vertexAttribArrayStride, newPointer);
}
}
}
}
return attribToUpdateMask;
}
void ContextGL::resetUpdatedAttributes(gl::AttributesMask attribMask)
{
const FunctionsGL *functions = getFunctions();
for (size_t attribIndex : attribMask)
{
const gl::VertexAttribute &attrib =
mState.getVertexArray()->getVertexAttributes()[attribIndex];
const gl::VertexBinding &binding =
(mState.getVertexArray()->getVertexBindings())[attrib.bindingIndex];
getStateManager()->bindBuffer(
gl::BufferBinding::Array,
GetImplAs<BufferGL>(binding.getBuffer().get())->getBufferID());
if (attrib.format->isPureInt())
{
functions->vertexAttribIPointer(static_cast<GLuint>(attribIndex),
attrib.format->channelCount,
gl::ToGLenum(attrib.format->vertexAttribType),
attrib.vertexAttribArrayStride, attrib.pointer);
}
else
{
functions->vertexAttribPointer(
static_cast<GLuint>(attribIndex), attrib.format->channelCount,
gl::ToGLenum(attrib.format->vertexAttribType), attrib.format->isNorm(),
attrib.vertexAttribArrayStride, attrib.pointer);
}
}
}
angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *context, angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *context,
gl::PrimitiveMode mode, gl::PrimitiveMode mode,
GLint first, GLint first,
...@@ -301,7 +377,39 @@ angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *cont ...@@ -301,7 +377,39 @@ angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instanceCount, GLsizei instanceCount,
GLuint baseInstance) GLuint baseInstance)
{ {
return drawArraysInstanced(context, mode, first, count, instanceCount); GLsizei adjustedInstanceCount = instanceCount;
const gl::Program *program = context->getState().getProgram();
if (program->usesMultiview())
{
adjustedInstanceCount *= program->getNumViews();
}
ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
const FunctionsGL *functions = getFunctions();
if (functions->drawArraysInstancedBaseInstance)
{
// GL 4.2+ or GL_EXT_base_instance
functions->drawArraysInstancedBaseInstance(ToGLenum(mode), first, count,
adjustedInstanceCount, baseInstance);
}
else
{
// GL 3.3+ or GLES 3.2+
// TODO(http://anglebug.com/3910): This is a temporary solution by setting and resetting
// pointer offset calling vertexAttribPointer Will refactor stateCache and pass baseInstance
// to setDrawArraysState to set pointer offset
gl::AttributesMask attribToResetMask =
updateAttributesForBaseInstance(program, baseInstance);
functions->drawArraysInstanced(ToGLenum(mode), first, count, adjustedInstanceCount);
resetUpdatedAttributes(attribToResetMask);
}
return angle::Result::Continue;
} }
angle::Result ContextGL::drawElements(const gl::Context *context, angle::Result ContextGL::drawElements(const gl::Context *context,
...@@ -373,10 +481,26 @@ angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::C ...@@ -373,10 +481,26 @@ angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::C
const FunctionsGL *functions = getFunctions(); const FunctionsGL *functions = getFunctions();
// GLES 3.2+ or GL 3.2+ if (functions->drawElementsInstancedBaseVertexBaseInstance)
// or GL_OES_draw_elements_base_vertex / GL_EXT_draw_elements_base_vertex {
// GL 4.2+ or GL_EXT_base_instance
functions->drawElementsInstancedBaseVertexBaseInstance(
ToGLenum(mode), count, ToGLenum(type), drawIndexPointer, adjustedInstanceCount,
baseVertex, baseInstance);
}
else
{
// GL 3.3+ or GLES 3.2+
// TODO(http://anglebug.com/3910): same as above
gl::AttributesMask attribToResetMask =
updateAttributesForBaseInstance(program, baseInstance);
functions->drawElementsInstancedBaseVertex(ToGLenum(mode), count, ToGLenum(type), functions->drawElementsInstancedBaseVertex(ToGLenum(mode), count, ToGLenum(type),
drawIndexPointer, adjustedInstanceCount, baseVertex); drawIndexPointer, adjustedInstanceCount,
baseVertex);
resetUpdatedAttributes(attribToResetMask);
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -255,6 +255,10 @@ class ContextGL : public ContextImpl ...@@ -255,6 +255,10 @@ class ContextGL : public ContextImpl
GLsizei instanceCount, GLsizei instanceCount,
const void **outIndices); const void **outIndices);
gl::AttributesMask updateAttributesForBaseInstance(const gl::Program *program,
GLuint baseInstance);
void resetUpdatedAttributes(gl::AttributesMask attribMask);
protected: protected:
std::shared_ptr<RendererGL> mRenderer; std::shared_ptr<RendererGL> mRenderer;
}; };
......
...@@ -133,6 +133,10 @@ class DrawBaseVertexBaseInstanceTest ...@@ -133,6 +133,10 @@ class DrawBaseVertexBaseInstanceTest
mRegularIndices[oi + j] = mIndices[j] + ov; mRegularIndices[oi + j] = mIndices[j] + ov;
} }
} }
std::iota(mInstancedArrayId.begin(), mInstancedArrayId.end(), 0.0f);
std::reverse_copy(mInstancedArrayId.begin(), mInstancedArrayId.end(),
mInstancedArrayColorId.begin());
} }
void SetUp() override { ANGLETestBase::ANGLETestSetUp(); } void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
...@@ -147,7 +151,7 @@ class DrawBaseVertexBaseInstanceTest ...@@ -147,7 +151,7 @@ class DrawBaseVertexBaseInstanceTest
return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance; return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance;
} }
std::string vertexShaderSource300(bool isDrawArrays, bool isMultiDraw) std::string vertexShaderSource300(bool isDrawArrays, bool isMultiDraw, bool divisorTest)
{ {
// Each color channel is to test the value of // Each color channel is to test the value of
// R: gl_InstanceID and gl_BaseInstance // R: gl_InstanceID and gl_BaseInstance
...@@ -162,18 +166,24 @@ class DrawBaseVertexBaseInstanceTest ...@@ -162,18 +166,24 @@ class DrawBaseVertexBaseInstanceTest
<< "#define kCountY " << kCountY << "\n" << "#define kCountY " << kCountY << "\n"
<< R"( << R"(
in vec2 vPosition; in vec2 vPosition;
)" << (useBaseInstanceBuiltin() ? "" : "in float vInstanceID;\n")
<< (!divisorTest ? "" : "in float vInstanceColorID;\n") << R"(
out vec4 color; out vec4 color;
void main() void main()
{ {
const float xStep = 1.0 / float(kCountX); const float xStep = 1.0 / float(kCountX);
const float yStep = 1.0 / float(kCountY); const float yStep = 1.0 / float(kCountY);
float x_id = float(gl_InstanceID)" float x_id = )"
<< (useBaseInstanceBuiltin() ? " + gl_BaseInstance" : "") << R"(); << (useBaseInstanceBuiltin() ? " float(gl_InstanceID + gl_BaseInstance);"
: "vInstanceID;")
<< "float x_color = "
<< (divisorTest ? "xStep * (vInstanceColorID + 1.0f);" : " 1.0 - xStep * x_id;")
<< R"(
float y_id = floor(float(gl_VertexID) / )" float y_id = floor(float(gl_VertexID) / )"
<< (isDrawArrays ? "6.0" : "4.0") << R"( + 0.01); << (isDrawArrays ? "6.0" : "4.0") << R"( + 0.01);
color = vec4( color = vec4(
1.0 - xStep * x_id, x_color,
1.0 - yStep * y_id, 1.0 - yStep * y_id,
)" << (useBaseVertexBuiltin() ? "1.0 - yStep * float(gl_BaseVertex) / 4.0" : "1.0") )" << (useBaseVertexBuiltin() ? "1.0 - yStep * float(gl_BaseVertex) / 4.0" : "1.0")
<< R"(, << R"(,
...@@ -201,14 +211,22 @@ void main() ...@@ -201,14 +211,22 @@ void main()
})"; })";
} }
void setupProgram(GLProgram &program, bool isDrawArrays = true, bool isMultiDraw = false) void setupProgram(GLProgram &program,
bool isDrawArrays = true,
bool isMultiDraw = false,
bool isDivisorTest = false)
{ {
program.makeRaster(vertexShaderSource300(isDrawArrays, isMultiDraw).c_str(), program.makeRaster(vertexShaderSource300(isDrawArrays, isMultiDraw, isDivisorTest).c_str(),
fragmentShaderSource300().c_str()); fragmentShaderSource300().c_str());
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
ASSERT_TRUE(program.valid()); ASSERT_TRUE(program.valid());
glUseProgram(program.get()); glUseProgram(program.get());
mPositionLoc = glGetAttribLocation(program.get(), "vPosition"); mPositionLoc = glGetAttribLocation(program.get(), "vPosition");
if (!useBaseInstanceBuiltin())
{
mInstanceIDLoc = glGetAttribLocation(program.get(), "vInstanceID");
mInstanceColorIDLoc = glGetAttribLocation(program.get(), "vInstanceColorID");
}
} }
void setupNonIndexedBuffers(GLBuffer &vertexBuffer) void setupNonIndexedBuffers(GLBuffer &vertexBuffer)
...@@ -233,6 +251,24 @@ void main() ...@@ -233,6 +251,24 @@ void main()
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
void setupInstanceIDBuffer(GLBuffer &instanceIDBuffer)
{
glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayId.size(),
mInstancedArrayId.data(), GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
}
void setupInstanceColorIDBuffer(GLBuffer &instanceIDBuffer)
{
glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayColorId.size(),
mInstancedArrayColorId.data(), GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
}
void setupRegularIndexedBuffer(GLBuffer &indexBuffer) void setupRegularIndexedBuffer(GLBuffer &indexBuffer)
{ {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
...@@ -242,53 +278,37 @@ void main() ...@@ -242,53 +278,37 @@ void main()
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
void doDrawCommons() void setupPositionVertexAttribPointer()
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray(mPositionLoc); glEnableVertexAttribArray(mPositionLoc);
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
} }
void doVertexAttribDivisor(GLint location, GLuint divisor) void setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)
{
if (getClientMajorVersion() <= 2)
{ {
ASSERT_TRUE(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays")); glEnableVertexAttribArray(instanceIDLoc);
glVertexAttribDivisorANGLE(location, divisor); glVertexAttribPointer(instanceIDLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
} glVertexAttribDivisor(instanceIDLoc, 1);
else
{
glVertexAttribDivisor(location, divisor);
}
} }
void doDrawArraysInstancedBaseInstance() void doDrawArraysInstancedBaseInstance()
{ {
doDrawCommons(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const uint32_t countPerDraw = kCountY * 6; const uint32_t countPerDraw = kCountY * 6;
if (useBaseInstanceBuiltin())
{
for (uint32_t i = 0; i < kCountX; i += 2) for (uint32_t i = 0; i < kCountX; i += 2)
{ {
glDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, 0, countPerDraw, 2, i); glDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, 0, countPerDraw, 2, i);
} }
} }
else
{
glDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, 0, countPerDraw, kCountX, 0);
}
}
void doMultiDrawArraysInstancedBaseInstance() void doMultiDrawArraysInstancedBaseInstance()
{ {
doDrawCommons(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const uint32_t countPerDraw = kCountY * 6; const uint32_t countPerDraw = kCountY * 6;
if (useBaseInstanceBuiltin())
{
const GLsizei drawCount = kCountX; const GLsizei drawCount = kCountX;
const std::vector<GLsizei> counts(drawCount, countPerDraw); const std::vector<GLsizei> counts(drawCount, countPerDraw);
const std::vector<GLsizei> firsts(drawCount, 0); const std::vector<GLsizei> firsts(drawCount, 0);
...@@ -302,29 +322,15 @@ void main() ...@@ -302,29 +322,15 @@ void main()
instanceCounts.data(), firsts.data(), instanceCounts.data(), firsts.data(),
baseInstances.data()); baseInstances.data());
} }
else
{
const GLsizei drawCount = 1;
const std::vector<GLsizei> counts(drawCount, countPerDraw);
const std::vector<GLsizei> firsts(drawCount, 0);
const std::vector<GLsizei> instanceCounts(drawCount, kCountX);
const std::vector<GLuint> baseInstances(drawCount, 0);
glMultiDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, drawCount, counts.data(),
instanceCounts.data(), firsts.data(),
baseInstances.data());
}
}
void doDrawElementsInstancedBaseVertexBaseInstance() void doDrawElementsInstancedBaseVertexBaseInstance()
{ {
doDrawCommons(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const uint32_t countPerDraw = 6; const uint32_t countPerDraw = 6;
for (uint32_t v = 0; v < kCountY; v++) for (uint32_t v = 0; v < kCountY; v++)
{ {
if (useBaseInstanceBuiltin())
{
for (uint32_t i = 0; i < kCountX; i += 2) for (uint32_t i = 0; i < kCountX; i += 2)
{ {
glDrawElementsInstancedBaseVertexBaseInstanceANGLE( glDrawElementsInstancedBaseVertexBaseInstanceANGLE(
...@@ -332,36 +338,27 @@ void main() ...@@ -332,36 +338,27 @@ void main()
reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 2, v * 4, i); reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 2, v * 4, i);
} }
} }
else
{
glDrawElementsInstancedBaseVertexBaseInstanceANGLE(
GL_TRIANGLES, countPerDraw, GL_UNSIGNED_SHORT,
reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), kCountX, v * 4, 0);
}
}
} }
// Call this after the *BaseVertexBaseInstance draw call to check if value of BaseVertex and // Call this after the *BaseVertexBaseInstance draw call to check if value of BaseVertex and
// BaseInstance are reset to zero // BaseInstance are reset to zero
void doDrawArraysBaseInstanceReset() void doDrawArraysBaseInstanceReset()
{ {
doDrawCommons(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6 * kCountY); glDrawArrays(GL_TRIANGLES, 0, 6 * kCountY);
} }
void doDrawElementsBaseVertexBaseInstanceReset() void doDrawElementsBaseVertexBaseInstanceReset()
{ {
doDrawCommons(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6 * kCountY, GL_UNSIGNED_SHORT, glDrawElements(GL_TRIANGLES, 6 * kCountY, GL_UNSIGNED_SHORT,
reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0))); reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)));
} }
void doMultiDrawElementsInstancedBaseVertexBaseInstance() void doMultiDrawElementsInstancedBaseVertexBaseInstance()
{ {
doDrawCommons(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (useBaseInstanceBuiltin())
{
const GLsizei drawCount = kCountX * kCountY / 2; const GLsizei drawCount = kCountX * kCountY / 2;
const std::vector<GLsizei> counts(drawCount, 6); const std::vector<GLsizei> counts(drawCount, 6);
const std::vector<GLsizei> instanceCounts(drawCount, 2); const std::vector<GLsizei> instanceCounts(drawCount, 2);
...@@ -384,25 +381,6 @@ void main() ...@@ -384,25 +381,6 @@ void main()
GL_TRIANGLES, GL_UNSIGNED_SHORT, drawCount, counts.data(), instanceCounts.data(), GL_TRIANGLES, GL_UNSIGNED_SHORT, drawCount, counts.data(), instanceCounts.data(),
indices.data(), baseVertices.data(), baseInstances.data()); indices.data(), baseVertices.data(), baseInstances.data());
} }
else
{
const GLsizei drawCount = kCountY;
const std::vector<GLsizei> counts(drawCount, 6);
const std::vector<GLsizei> instanceCounts(drawCount, kCountX);
const std::vector<GLvoid *> indices(drawCount, 0);
std::vector<GLint> baseVertices(drawCount);
const std::vector<GLuint> baseInstances(drawCount, 0);
for (uint32_t v = 0; v < drawCount; v++)
{
baseVertices[v] = v * 4;
}
glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(
GL_TRIANGLES, GL_UNSIGNED_SHORT, drawCount, counts.data(), instanceCounts.data(),
indices.data(), baseVertices.data(), baseInstances.data());
}
}
void checkDrawResult(bool hasBaseVertex, bool oneColumn = false) void checkDrawResult(bool hasBaseVertex, bool oneColumn = false)
{ {
...@@ -474,9 +452,14 @@ void main() ...@@ -474,9 +452,14 @@ void main()
std::vector<GLushort> mIndices; std::vector<GLushort> mIndices;
std::vector<GLfloat> mVertices; std::vector<GLfloat> mVertices;
std::vector<GLfloat> mNonIndexedVertices; std::vector<GLfloat> mNonIndexedVertices;
// Used when gl_BaseInstance is not used
std::array<GLfloat, kCountX> mInstancedArrayId;
std::array<GLfloat, kCountX> mInstancedArrayColorId;
// Used for regular draw calls without base vertex base instance // Used for regular draw calls without base vertex base instance
std::vector<GLushort> mRegularIndices; std::vector<GLushort> mRegularIndices;
GLint mPositionLoc; GLint mPositionLoc;
GLuint mInstanceIDLoc;
GLuint mInstanceColorIDLoc;
}; };
// Tests that compile a program with the extension succeeds // Tests that compile a program with the extension succeeds
...@@ -493,6 +476,58 @@ TEST_P(DrawBaseVertexBaseInstanceTest, CanCompile) ...@@ -493,6 +476,58 @@ TEST_P(DrawBaseVertexBaseInstanceTest, CanCompile)
setupProgram(p3, false, true); setupProgram(p3, false, true);
} }
// Tests if baseInstance works properly with instanced array with non-zero divisor
TEST_P(DrawBaseVertexBaseInstanceTest, BaseInstanceDivisor)
{
ANGLE_SKIP_TEST_IF(!requestExtensions());
ANGLE_SKIP_TEST_IF(useBaseInstanceBuiltin());
GLProgram program;
setupProgram(program, true, false, true);
GLBuffer nonIndexedVertexBuffer;
setupNonIndexedBuffers(nonIndexedVertexBuffer);
setupPositionVertexAttribPointer();
GLBuffer instanceIDBuffer;
GLBuffer instanceColorIDBuffer;
setupInstanceIDBuffer(instanceIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
setupInstanceColorIDBuffer(instanceColorIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
doDrawArraysInstancedBaseInstance();
EXPECT_GL_NO_ERROR();
checkDrawResult(false);
doDrawArraysBaseInstanceReset();
EXPECT_GL_NO_ERROR();
checkDrawResult(false, true);
GLProgram programIndexed;
setupProgram(programIndexed, false, false, true);
GLBuffer indexBuffer;
GLBuffer vertexBuffer;
setupIndexedBuffers(vertexBuffer, indexBuffer);
setupPositionVertexAttribPointer();
glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
glBindBuffer(GL_ARRAY_BUFFER, instanceColorIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
doDrawElementsInstancedBaseVertexBaseInstance();
EXPECT_GL_NO_ERROR();
checkDrawResult(true);
setupRegularIndexedBuffer(indexBuffer);
doDrawElementsBaseVertexBaseInstanceReset();
EXPECT_GL_NO_ERROR();
checkDrawResult(false, true);
}
// Tests basic functionality of glDrawArraysInstancedBaseInstance // Tests basic functionality of glDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance) TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance)
{ {
...@@ -513,10 +548,21 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance) ...@@ -513,10 +548,21 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance)
} }
ANGLE_SKIP_TEST_IF(!requestExtensions()); ANGLE_SKIP_TEST_IF(!requestExtensions());
GLBuffer vertexBuffer;
setupNonIndexedBuffers(vertexBuffer);
GLProgram program; GLProgram program;
setupProgram(program, true); setupProgram(program, true);
GLBuffer vertexBuffer;
setupNonIndexedBuffers(vertexBuffer);
setupPositionVertexAttribPointer();
GLBuffer instanceIDBuffer;
if (!useBaseInstanceBuiltin())
{
setupInstanceIDBuffer(instanceIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
}
doDrawArraysInstancedBaseInstance(); doDrawArraysInstancedBaseInstance();
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
checkDrawResult(false); checkDrawResult(false);
...@@ -538,10 +584,21 @@ TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance) ...@@ -538,10 +584,21 @@ TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
} }
ANGLE_SKIP_TEST_IF(!requestExtensions()); ANGLE_SKIP_TEST_IF(!requestExtensions());
GLBuffer vertexBuffer;
setupNonIndexedBuffers(vertexBuffer);
GLProgram program; GLProgram program;
setupProgram(program, true, true); setupProgram(program, true, true);
GLBuffer vertexBuffer;
setupNonIndexedBuffers(vertexBuffer);
setupPositionVertexAttribPointer();
GLBuffer instanceIDBuffer;
if (!useBaseInstanceBuiltin())
{
setupInstanceIDBuffer(instanceIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
}
doMultiDrawArraysInstancedBaseInstance(); doMultiDrawArraysInstancedBaseInstance();
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
checkDrawResult(false); checkDrawResult(false);
...@@ -554,11 +611,22 @@ TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance) ...@@ -554,11 +611,22 @@ TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance) TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance)
{ {
ANGLE_SKIP_TEST_IF(!requestExtensions()); ANGLE_SKIP_TEST_IF(!requestExtensions());
GLProgram program;
setupProgram(program, false);
GLBuffer indexBuffer; GLBuffer indexBuffer;
GLBuffer vertexBuffer; GLBuffer vertexBuffer;
setupIndexedBuffers(vertexBuffer, indexBuffer); setupIndexedBuffers(vertexBuffer, indexBuffer);
GLProgram program; setupPositionVertexAttribPointer();
setupProgram(program, false);
GLBuffer instanceIDBuffer;
if (!useBaseInstanceBuiltin())
{
setupInstanceIDBuffer(instanceIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
}
doDrawElementsInstancedBaseVertexBaseInstance(); doDrawElementsInstancedBaseVertexBaseInstance();
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
checkDrawResult(true); checkDrawResult(true);
...@@ -573,11 +641,22 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstan ...@@ -573,11 +641,22 @@ TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstan
TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance) TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance)
{ {
ANGLE_SKIP_TEST_IF(!requestExtensions()); ANGLE_SKIP_TEST_IF(!requestExtensions());
GLProgram program;
setupProgram(program, false, true);
GLBuffer indexBuffer; GLBuffer indexBuffer;
GLBuffer vertexBuffer; GLBuffer vertexBuffer;
setupIndexedBuffers(vertexBuffer, indexBuffer); setupIndexedBuffers(vertexBuffer, indexBuffer);
GLProgram program; setupPositionVertexAttribPointer();
setupProgram(program, false, true);
GLBuffer instanceIDBuffer;
if (!useBaseInstanceBuiltin())
{
setupInstanceIDBuffer(instanceIDBuffer);
setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
}
doMultiDrawElementsInstancedBaseVertexBaseInstance(); doMultiDrawElementsInstancedBaseVertexBaseInstance();
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
checkDrawResult(true); checkDrawResult(true);
......
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