Commit 1b7ed0ef by Jamie Madill Committed by Commit Bot

D3D11: Minor optimizations to Renderer11.

This moves the skipDraw logic into applyPrimitiveType, since it's more efficient to only check the primitive type once. Also merges the draw*Impl and genericDraw* methods, since the generic* methods weren't really doing anything anymore, and all the state logic lives in StateManager::updateState. This series of small optimizations gives about a 15% improvement on the draw call benchmark for the D3D11 backend with the null driver. BUG=angleproject:1155 Change-Id: I299213da6d1bbcb08691d5b50162e6cae16cb4bb Reviewed-on: https://chromium-review.googlesource.com/666044Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 61491505
......@@ -160,7 +160,7 @@ gl::Error Context11::finish()
gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawArrays(context, mode, first, count, 0);
return mRenderer->drawArrays(context, mode, first, count, 0);
}
gl::Error Context11::drawArraysInstanced(const gl::Context *context,
......@@ -170,7 +170,7 @@ gl::Error Context11::drawArraysInstanced(const gl::Context *context,
GLsizei instanceCount)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawArrays(context, mode, first, count, instanceCount);
return mRenderer->drawArrays(context, mode, first, count, instanceCount);
}
gl::Error Context11::drawElements(const gl::Context *context,
......@@ -180,7 +180,7 @@ gl::Error Context11::drawElements(const gl::Context *context,
const void *indices)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
return mRenderer->drawElements(context, mode, count, type, indices, 0);
}
gl::Error Context11::drawElementsInstanced(const gl::Context *context,
......@@ -191,7 +191,7 @@ gl::Error Context11::drawElementsInstanced(const gl::Context *context,
GLsizei instances)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawElements(context, mode, count, type, indices, instances);
return mRenderer->drawElements(context, mode, count, type, indices, instances);
}
gl::Error Context11::drawRangeElements(const gl::Context *context,
......@@ -203,7 +203,7 @@ gl::Error Context11::drawRangeElements(const gl::Context *context,
const void *indices)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
return mRenderer->drawElements(context, mode, count, type, indices, 0);
}
gl::Error Context11::drawArraysIndirect(const gl::Context *context,
......@@ -211,7 +211,7 @@ gl::Error Context11::drawArraysIndirect(const gl::Context *context,
const void *indirect)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawIndirect(context, mode, GL_NONE, indirect);
return mRenderer->drawArraysIndirect(context, mode, indirect);
}
gl::Error Context11::drawElementsIndirect(const gl::Context *context,
......@@ -220,7 +220,7 @@ gl::Error Context11::drawElementsIndirect(const gl::Context *context,
const void *indirect)
{
ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawIndirect(context, mode, type, indirect);
return mRenderer->drawElementsIndirect(context, mode, type, indirect);
}
GLenum Context11::getResetStatus()
......
......@@ -425,6 +425,12 @@ void PopulateFormatDeviceCaps(ID3D11Device *device,
}
}
bool CullsEverything(const gl::State &glState)
{
return (glState.getRasterizerState().cullFace &&
glState.getRasterizerState().cullMode == GL_FRONT_AND_BACK);
}
} // anonymous namespace
Renderer11::Renderer11(egl::Display *display)
......@@ -1395,7 +1401,7 @@ void *Renderer11::getD3DDevice()
return reinterpret_cast<void *>(mDevice);
}
bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
bool Renderer11::applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count)
{
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
......@@ -1404,6 +1410,19 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
switch (mode)
{
case GL_POINTS:
{
bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
// ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
// which affects varying interpolation. Since the value of gl_PointSize is
// undefined when not written, just skip drawing to avoid unexpected results.
if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
{
// Notify developers of risking undefined behavior.
WARN() << "Point rendering without writing to gl_PointSize.";
return false;
}
// If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
// must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
......@@ -1416,6 +1435,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
}
minCount = 1;
break;
}
case GL_LINES:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
minCount = 2;
......@@ -1430,16 +1450,16 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
break;
case GL_TRIANGLES:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
minCount = 3;
minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
break;
case GL_TRIANGLE_STRIP:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
minCount = 3;
minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
break;
// emulate fans via rewriting index buffer
case GL_TRIANGLE_FAN:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
minCount = 3;
minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
break;
default:
UNREACHABLE();
......@@ -1451,16 +1471,31 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
return count >= minCount;
}
gl::Error Renderer11::drawArraysImpl(const gl::Context *context,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances)
gl::Error Renderer11::drawArrays(const gl::Context *context,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances)
{
const auto &glState = context->getGLState();
gl::Program *program = glState.getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
const auto &glState = context->getGLState();
if (!applyPrimitiveType(glState, mode, count))
{
return gl::NoError();
}
ANGLE_TRY(
mStateManager.applyVertexBuffer(context, mode, startVertex, count, instances, nullptr));
if (glState.isTransformFeedbackActiveUnpaused())
{
ANGLE_TRY(markTransformFeedbackUsage(context));
}
gl::Program *program = glState.getProgram();
ASSERT(program != nullptr);
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
{
......@@ -1563,14 +1598,24 @@ gl::Error Renderer11::drawArraysImpl(const gl::Context *context,
return gl::NoError();
}
gl::Error Renderer11::drawElementsImpl(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instances)
gl::Error Renderer11::drawElements(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instances)
{
const auto &glState = context->getGLState();
if (!applyPrimitiveType(glState, mode, count))
{
return gl::NoError();
}
// Transform feedback is not allowed for DrawElements, this error should have been caught at the
// API validation layer.
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
TranslatedIndexData indexInfo;
const gl::Program *program = glState.getProgram();
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
......@@ -1667,12 +1712,14 @@ gl::Error Renderer11::drawElementsImpl(const gl::Context *context,
return gl::NoError();
}
gl::Error Renderer11::drawArraysIndirectImpl(const gl::Context *context,
GLenum mode,
const void *indirect)
gl::Error Renderer11::drawArraysIndirect(const gl::Context *context,
GLenum mode,
const void *indirect)
{
const auto &glState = context->getGLState();
if (skipDraw(glState, mode))
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
{
return gl::NoError();
}
......@@ -1715,13 +1762,15 @@ gl::Error Renderer11::drawArraysIndirectImpl(const gl::Context *context,
return gl::NoError();
}
gl::Error Renderer11::drawElementsIndirectImpl(const gl::Context *context,
GLenum mode,
GLenum type,
const void *indirect)
gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
GLenum mode,
GLenum type,
const void *indirect)
{
const auto &glState = context->getGLState();
if (skipDraw(glState, mode))
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
{
return gl::NoError();
}
......@@ -3788,92 +3837,6 @@ ContextImpl *Renderer11::createContext(const gl::ContextState &state)
return new Context11(state, this);
}
gl::Error Renderer11::genericDrawElements(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instances)
{
const auto &glState = context->getGLState();
gl::Program *program = glState.getProgram();
ASSERT(program != nullptr);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
bool usesPointSize = programD3D->usesPointSize();
if (!applyPrimitiveType(mode, count, usesPointSize))
{
return gl::NoError();
}
// Transform feedback is not allowed for DrawElements, this error should have been caught at the
// API validation layer.
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
if (!skipDraw(glState, mode))
{
ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances));
}
return gl::NoError();
}
gl::Error Renderer11::genericDrawArrays(const gl::Context *context,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances)
{
const auto &glState = context->getGLState();
gl::Program *program = glState.getProgram();
ASSERT(program != nullptr);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
if (!applyPrimitiveType(mode, count, programD3D->usesPointSize()))
{
return gl::NoError();
}
ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, first, count, instances, nullptr));
if (!skipDraw(glState, mode))
{
ANGLE_TRY(drawArraysImpl(context, mode, first, count, instances));
if (glState.isTransformFeedbackActiveUnpaused())
{
ANGLE_TRY(markTransformFeedbackUsage(context));
}
}
return gl::NoError();
}
gl::Error Renderer11::genericDrawIndirect(const gl::Context *context,
GLenum mode,
GLenum type,
const void *indirect)
{
const auto &glState = context->getGLState();
ASSERT(!glState.isTransformFeedbackActiveUnpaused());
gl::Program *program = glState.getProgram();
ASSERT(program != nullptr);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
applyPrimitiveType(mode, 0, programD3D->usesPointSize());
if (type == GL_NONE)
{
ANGLE_TRY(drawArraysIndirectImpl(context, mode, indirect));
}
else
{
ANGLE_TRY(drawElementsIndirectImpl(context, mode, type, indirect));
}
return gl::NoError();
}
FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
{
return new Framebuffer11(state, this);
......
......@@ -146,7 +146,7 @@ class Renderer11 : public RendererD3D
HANDLE shareHandle,
const egl::AttributeMap &attribs) const override;
bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
bool applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count);
// lost device
bool testDeviceLost() override;
......@@ -380,23 +380,24 @@ class Renderer11 : public RendererD3D
egl::Error getEGLDevice(DeviceImpl **device) override;
gl::Error genericDrawArrays(const gl::Context *context,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances);
gl::Error drawArrays(const gl::Context *context,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances);
gl::Error genericDrawElements(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instances);
gl::Error drawElements(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instances);
gl::Error genericDrawIndirect(const gl::Context *context,
GLenum mode,
GLenum type,
const void *indirect);
gl::Error drawArraysIndirect(const gl::Context *context, GLenum mode, const void *indirect);
gl::Error drawElementsIndirect(const gl::Context *context,
GLenum mode,
GLenum type,
const void *indirect);
// Necessary hack for default framebuffers in D3D.
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
......@@ -460,23 +461,6 @@ class Renderer11 : public RendererD3D
bool canSelectViewInVertexShader() const override;
private:
gl::Error drawArraysImpl(const gl::Context *context,
GLenum mode,
GLint startVertex,
GLsizei count,
GLsizei instances);
gl::Error drawElementsImpl(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
const void *indices,
GLsizei instances);
gl::Error drawArraysIndirectImpl(const gl::Context *context, GLenum mode, const void *indirect);
gl::Error drawElementsIndirectImpl(const gl::Context *context,
GLenum mode,
GLenum type,
const void *indirect);
void generateCaps(gl::Caps *outCaps,
gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
......
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