Commit c7b0cf2a by Jamie Madill Committed by Commit Bot

D3D11: Remove "fast path" check in DrawElements.

This was a bit of an anti-pattern. Many draw calls were being handled in the "slow" path, so the repeated checks were slowing the draw calls down more than the fast path was speeding things up. The new code tries to do all the checking for index ranges and restart index once only, and lazily when possible. The 'start' vertex is a bit of a special case - we known when the primitive restart index is not enabled, this will be always the same as the 'base' vertex (zero if the base vertex is not enabled - only currently available through draw indirect commands). In future work we can look at implementing a lazy evaluation for draw indirect commands so we don't need to do a check there either. Reduces overhead in the D3D11 indexed rendering perf test such that it leads to an increased score of about 5%. BUG=angleproject:2229 Change-Id: I6330f30b66d1810624d03f4e7a012bf2391a3bf3 Reviewed-on: https://chromium-review.googlesource.com/764677 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5a654f5f
......@@ -1645,41 +1645,23 @@ gl::Error Renderer11::drawElements(const gl::Context *context,
// API validation layer.
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
TranslatedIndexData indexInfo;
const gl::Program *program = glState.getProgram();
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>();
if (!DrawCallNeedsTranslation(context, mode) &&
!UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type))
{
ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
&indexInfo));
DrawCallVertexParams vertexParams(0, 0, instances);
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, &indexInfo));
if (adjustedInstanceCount > 0)
{
mDeviceContext->DrawIndexedInstanced(count, adjustedInstanceCount, 0, 0, 0);
}
else
{
mDeviceContext->DrawIndexed(count, 0, 0);
}
return gl::NoError();
}
ANGLE_TRY(
mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange, &indexInfo));
DrawCallVertexParams vertexParams(lazyIndexRange, 0, instances);
bool usePrimitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
DrawCallVertexParams vertexParams(!usePrimitiveRestartWorkaround, lazyIndexRange, 0, instances);
TranslatedIndexData indexInfo;
ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
usePrimitiveRestartWorkaround, &indexInfo));
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, &indexInfo));
int startVertex = static_cast<int>(vertexParams.firstVertex());
int baseVertex = -startVertex;
const gl::Program *program = glState.getProgram();
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
if (mode == GL_LINE_LOOP)
{
return drawLineLoop(context, count, type, indices, baseVertex, adjustedInstanceCount);
......@@ -1810,11 +1792,15 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
// TODO(jmadill): Remove the if statement and compute indirect parameters lazily.
bool usePrimitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
TranslatedIndexData indexInfo;
if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type))
{
ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, gl::HasIndexRange(),
&indexInfo));
usePrimitiveRestartWorkaround, &indexInfo));
DrawCallVertexParams vertexParams(0, 0, 0);
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, &indexInfo));
ID3D11Buffer *buffer = nullptr;
......@@ -1840,10 +1826,10 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
reinterpret_cast<const void *>(static_cast<uintptr_t>(firstIndex * typeInfo.bytes));
gl::HasIndexRange lazyIndexRange(const_cast<gl::Context *>(context), count, type, indices);
ANGLE_TRY(
mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange, &indexInfo));
ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
usePrimitiveRestartWorkaround, &indexInfo));
DrawCallVertexParams vertexParams(lazyIndexRange, baseVertex, instances);
DrawCallVertexParams vertexParams(false, lazyIndexRange, baseVertex, instances);
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, &indexInfo));
......
......@@ -2564,15 +2564,13 @@ gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
GLsizei count,
GLenum type,
const gl::HasIndexRange &lazyIndexRange,
bool usePrimitiveRestartWorkaround,
TranslatedIndexData *indexInfo)
{
const auto &glState = context->getGLState();
gl::VertexArray *vao = glState.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
bool usePrimitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
GLenum dstType =
GetIndexTranslationDestType(type, lazyIndexRange, usePrimitiveRestartWorkaround);
......@@ -2992,25 +2990,36 @@ DrawCallVertexParams::DrawCallVertexParams(GLint firstVertex,
: mHasIndexRange(nullptr),
mFirstVertex(firstVertex),
mVertexCount(vertexCount),
mInstances(instances)
mInstances(instances),
mBaseVertex(0)
{
}
// Use when in a drawElements call.
DrawCallVertexParams::DrawCallVertexParams(const gl::HasIndexRange &hasIndexRange,
DrawCallVertexParams::DrawCallVertexParams(bool firstVertexDefinitelyZero,
const gl::HasIndexRange &hasIndexRange,
GLint baseVertex,
GLsizei instances)
: mHasIndexRange(&hasIndexRange),
mFirstVertex(baseVertex),
mFirstVertex(),
mVertexCount(0),
mInstances(instances)
mInstances(instances),
mBaseVertex(baseVertex)
{
if (firstVertexDefinitelyZero)
{
mFirstVertex = baseVertex;
}
}
GLint DrawCallVertexParams::firstVertex() const
{
ensureResolved();
return mFirstVertex;
if (!mFirstVertex.valid())
{
ensureResolved();
ASSERT(mFirstVertex.valid());
}
return mFirstVertex.value();
}
GLsizei DrawCallVertexParams::vertexCount() const
......@@ -3028,11 +3037,13 @@ void DrawCallVertexParams::ensureResolved() const
{
if (mHasIndexRange)
{
ASSERT(!mFirstVertex.valid() || mFirstVertex == mBaseVertex);
// Resolve the index range now if we need to.
const gl::IndexRange &indexRange = mHasIndexRange->getIndexRange().value();
mFirstVertex += static_cast<GLint>(indexRange.start);
mVertexCount = static_cast<GLsizei>(indexRange.vertexCount());
mHasIndexRange = nullptr;
const auto &indexRange = mHasIndexRange->getIndexRange().value();
mFirstVertex = mBaseVertex + static_cast<GLint>(indexRange.start);
mVertexCount = static_cast<GLsizei>(indexRange.vertexCount());
mHasIndexRange = nullptr;
}
}
......
......@@ -148,10 +148,14 @@ class DrawCallVertexParams final : angle::NonCopyable
DrawCallVertexParams(GLint firstVertex, GLsizei vertexCount, GLsizei instances);
// Use when in a drawElements call.
DrawCallVertexParams(const gl::HasIndexRange &hasIndexRange,
DrawCallVertexParams(bool firstVertexDefinitelyZero,
const gl::HasIndexRange &hasIndexRange,
GLint baseVertex,
GLsizei instances);
// It should be possible to also use an overload to handle the 'slow' indirect draw path.
// TODO(jmadill): Indirect draw slow path overload.
GLint firstVertex() const;
GLsizei vertexCount() const;
GLsizei instances() const;
......@@ -160,9 +164,10 @@ class DrawCallVertexParams final : angle::NonCopyable
void ensureResolved() const;
mutable const gl::HasIndexRange *mHasIndexRange;
mutable GLint mFirstVertex;
mutable Optional<GLint> mFirstVertex;
mutable GLsizei mVertexCount;
GLsizei mInstances;
GLint mBaseVertex;
};
class StateManager11 final : angle::NonCopyable
......@@ -269,6 +274,7 @@ class StateManager11 final : angle::NonCopyable
GLsizei count,
GLenum type,
const gl::HasIndexRange &lazyIndexRange,
bool usePrimitiveRestartWorkaround,
TranslatedIndexData *indexInfo);
bool setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
......
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