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,
ASSERT(count > 0);
ANGLE_TRY(mRenderer->getStateManager()->updateState(
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,
......@@ -280,7 +280,7 @@ angle::Result Context11::drawArraysInstanced(const gl::Context *context,
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);
return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0);
}
angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context,
......@@ -290,7 +290,10 @@ angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instanceCount,
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,
......@@ -380,7 +383,8 @@ angle::Result Context11::drawArraysIndirect(const gl::Context *context,
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count,
gl::DrawElementsType::InvalidEnum,
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
{
......
......@@ -1476,7 +1476,8 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
gl::PrimitiveMode mode,
GLint firstVertex,
GLsizei vertexCount,
GLsizei instanceCount)
GLsizei instanceCount,
GLuint baseInstance)
{
if (mStateManager.getCullEverything())
{
......@@ -1520,7 +1521,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
if (adjustedInstanceCount == 0)
{
mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, 0);
mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
return angle::Result::Continue;
}
......@@ -1534,7 +1535,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
{
ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(
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
......@@ -1554,7 +1555,7 @@ angle::Result Renderer11::drawArrays(const gl::Context *context,
}
else
{
mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, 0);
mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, baseInstance);
}
return angle::Result::Continue;
}
......
......@@ -410,7 +410,8 @@ class Renderer11 : public RendererD3D
gl::PrimitiveMode mode,
GLint firstVertex,
GLsizei vertexCount,
GLsizei instanceCount);
GLsizei instanceCount,
GLuint baseInstance);
angle::Result drawElements(const gl::Context *context,
gl::PrimitiveMode mode,
GLint startVertex,
......
......@@ -294,6 +294,82 @@ angle::Result ContextGL::drawArraysInstanced(const gl::Context *context,
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,
gl::PrimitiveMode mode,
GLint first,
......@@ -301,7 +377,39 @@ angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instanceCount,
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,
......@@ -373,10 +481,26 @@ angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::C
const FunctionsGL *functions = getFunctions();
// GLES 3.2+ or GL 3.2+
// or GL_OES_draw_elements_base_vertex / GL_EXT_draw_elements_base_vertex
functions->drawElementsInstancedBaseVertex(ToGLenum(mode), count, ToGLenum(type),
drawIndexPointer, adjustedInstanceCount, baseVertex);
if (functions->drawElementsInstancedBaseVertexBaseInstance)
{
// 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),
drawIndexPointer, adjustedInstanceCount,
baseVertex);
resetUpdatedAttributes(attribToResetMask);
}
return angle::Result::Continue;
}
......
......@@ -255,6 +255,10 @@ class ContextGL : public ContextImpl
GLsizei instanceCount,
const void **outIndices);
gl::AttributesMask updateAttributesForBaseInstance(const gl::Program *program,
GLuint baseInstance);
void resetUpdatedAttributes(gl::AttributesMask attribMask);
protected:
std::shared_ptr<RendererGL> mRenderer;
};
......
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