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() ...@@ -160,7 +160,7 @@ gl::Error Context11::finish()
gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count) gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); 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, gl::Error Context11::drawArraysInstanced(const gl::Context *context,
...@@ -170,7 +170,7 @@ gl::Error Context11::drawArraysInstanced(const gl::Context *context, ...@@ -170,7 +170,7 @@ gl::Error Context11::drawArraysInstanced(const gl::Context *context,
GLsizei instanceCount) GLsizei instanceCount)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); 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, gl::Error Context11::drawElements(const gl::Context *context,
...@@ -180,7 +180,7 @@ gl::Error Context11::drawElements(const gl::Context *context, ...@@ -180,7 +180,7 @@ gl::Error Context11::drawElements(const gl::Context *context,
const void *indices) const void *indices)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); 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, gl::Error Context11::drawElementsInstanced(const gl::Context *context,
...@@ -191,7 +191,7 @@ gl::Error Context11::drawElementsInstanced(const gl::Context *context, ...@@ -191,7 +191,7 @@ gl::Error Context11::drawElementsInstanced(const gl::Context *context,
GLsizei instances) GLsizei instances)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); 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, gl::Error Context11::drawRangeElements(const gl::Context *context,
...@@ -203,7 +203,7 @@ gl::Error Context11::drawRangeElements(const gl::Context *context, ...@@ -203,7 +203,7 @@ gl::Error Context11::drawRangeElements(const gl::Context *context,
const void *indices) const void *indices)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); 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, gl::Error Context11::drawArraysIndirect(const gl::Context *context,
...@@ -211,7 +211,7 @@ gl::Error Context11::drawArraysIndirect(const gl::Context *context, ...@@ -211,7 +211,7 @@ gl::Error Context11::drawArraysIndirect(const gl::Context *context,
const void *indirect) const void *indirect)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); 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, gl::Error Context11::drawElementsIndirect(const gl::Context *context,
...@@ -220,7 +220,7 @@ gl::Error Context11::drawElementsIndirect(const gl::Context *context, ...@@ -220,7 +220,7 @@ gl::Error Context11::drawElementsIndirect(const gl::Context *context,
const void *indirect) const void *indirect)
{ {
ANGLE_TRY(prepareForDrawCall(context, mode)); ANGLE_TRY(prepareForDrawCall(context, mode));
return mRenderer->genericDrawIndirect(context, mode, type, indirect); return mRenderer->drawElementsIndirect(context, mode, type, indirect);
} }
GLenum Context11::getResetStatus() GLenum Context11::getResetStatus()
......
...@@ -425,6 +425,12 @@ void PopulateFormatDeviceCaps(ID3D11Device *device, ...@@ -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 } // anonymous namespace
Renderer11::Renderer11(egl::Display *display) Renderer11::Renderer11(egl::Display *display)
...@@ -1395,7 +1401,7 @@ void *Renderer11::getD3DDevice() ...@@ -1395,7 +1401,7 @@ void *Renderer11::getD3DDevice()
return reinterpret_cast<void *>(mDevice); 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; D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
...@@ -1404,6 +1410,19 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi ...@@ -1404,6 +1410,19 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
switch (mode) switch (mode)
{ {
case GL_POINTS: 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 // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
// must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST. // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation) if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
...@@ -1416,6 +1435,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi ...@@ -1416,6 +1435,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
} }
minCount = 1; minCount = 1;
break; break;
}
case GL_LINES: case GL_LINES:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
minCount = 2; minCount = 2;
...@@ -1430,16 +1450,16 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi ...@@ -1430,16 +1450,16 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
break; break;
case GL_TRIANGLES: case GL_TRIANGLES:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
minCount = 3; minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
break; break;
case GL_TRIANGLE_STRIP: case GL_TRIANGLE_STRIP:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
minCount = 3; minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
break; break;
// emulate fans via rewriting index buffer // emulate fans via rewriting index buffer
case GL_TRIANGLE_FAN: case GL_TRIANGLE_FAN:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
minCount = 3; minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -1451,16 +1471,31 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi ...@@ -1451,16 +1471,31 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
return count >= minCount; return count >= minCount;
} }
gl::Error Renderer11::drawArraysImpl(const gl::Context *context, gl::Error Renderer11::drawArrays(const gl::Context *context,
GLenum mode, GLenum mode,
GLint startVertex, GLint startVertex,
GLsizei count, GLsizei count,
GLsizei instances) GLsizei instances)
{ {
const auto &glState = context->getGLState(); 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(); gl::Program *program = glState.getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); ASSERT(program != nullptr);
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused()) if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
{ {
...@@ -1563,7 +1598,7 @@ gl::Error Renderer11::drawArraysImpl(const gl::Context *context, ...@@ -1563,7 +1598,7 @@ gl::Error Renderer11::drawArraysImpl(const gl::Context *context,
return gl::NoError(); return gl::NoError();
} }
gl::Error Renderer11::drawElementsImpl(const gl::Context *context, gl::Error Renderer11::drawElements(const gl::Context *context,
GLenum mode, GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
...@@ -1571,6 +1606,16 @@ gl::Error Renderer11::drawElementsImpl(const gl::Context *context, ...@@ -1571,6 +1606,16 @@ gl::Error Renderer11::drawElementsImpl(const gl::Context *context,
GLsizei instances) GLsizei instances)
{ {
const auto &glState = context->getGLState(); 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; TranslatedIndexData indexInfo;
const gl::Program *program = glState.getProgram(); const gl::Program *program = glState.getProgram();
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
...@@ -1667,12 +1712,14 @@ gl::Error Renderer11::drawElementsImpl(const gl::Context *context, ...@@ -1667,12 +1712,14 @@ gl::Error Renderer11::drawElementsImpl(const gl::Context *context,
return gl::NoError(); return gl::NoError();
} }
gl::Error Renderer11::drawArraysIndirectImpl(const gl::Context *context, gl::Error Renderer11::drawArraysIndirect(const gl::Context *context,
GLenum mode, GLenum mode,
const void *indirect) const void *indirect)
{ {
const auto &glState = context->getGLState(); 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(); return gl::NoError();
} }
...@@ -1715,13 +1762,15 @@ gl::Error Renderer11::drawArraysIndirectImpl(const gl::Context *context, ...@@ -1715,13 +1762,15 @@ gl::Error Renderer11::drawArraysIndirectImpl(const gl::Context *context,
return gl::NoError(); return gl::NoError();
} }
gl::Error Renderer11::drawElementsIndirectImpl(const gl::Context *context, gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
const void *indirect) const void *indirect)
{ {
const auto &glState = context->getGLState(); 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(); return gl::NoError();
} }
...@@ -3788,92 +3837,6 @@ ContextImpl *Renderer11::createContext(const gl::ContextState &state) ...@@ -3788,92 +3837,6 @@ ContextImpl *Renderer11::createContext(const gl::ContextState &state)
return new Context11(state, this); 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) FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
{ {
return new Framebuffer11(state, this); return new Framebuffer11(state, this);
......
...@@ -146,7 +146,7 @@ class Renderer11 : public RendererD3D ...@@ -146,7 +146,7 @@ class Renderer11 : public RendererD3D
HANDLE shareHandle, HANDLE shareHandle,
const egl::AttributeMap &attribs) const override; 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 // lost device
bool testDeviceLost() override; bool testDeviceLost() override;
...@@ -380,20 +380,21 @@ class Renderer11 : public RendererD3D ...@@ -380,20 +380,21 @@ class Renderer11 : public RendererD3D
egl::Error getEGLDevice(DeviceImpl **device) override; egl::Error getEGLDevice(DeviceImpl **device) override;
gl::Error genericDrawArrays(const gl::Context *context, gl::Error drawArrays(const gl::Context *context,
GLenum mode, GLenum mode,
GLint first, GLint startVertex,
GLsizei count, GLsizei count,
GLsizei instances); GLsizei instances);
gl::Error genericDrawElements(const gl::Context *context, gl::Error drawElements(const gl::Context *context,
GLenum mode, GLenum mode,
GLsizei count, GLsizei count,
GLenum type, GLenum type,
const void *indices, const void *indices,
GLsizei instances); GLsizei instances);
gl::Error genericDrawIndirect(const gl::Context *context, gl::Error drawArraysIndirect(const gl::Context *context, GLenum mode, const void *indirect);
gl::Error drawElementsIndirect(const gl::Context *context,
GLenum mode, GLenum mode,
GLenum type, GLenum type,
const void *indirect); const void *indirect);
...@@ -460,23 +461,6 @@ class Renderer11 : public RendererD3D ...@@ -460,23 +461,6 @@ class Renderer11 : public RendererD3D
bool canSelectViewInVertexShader() const override; bool canSelectViewInVertexShader() const override;
private: 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, void generateCaps(gl::Caps *outCaps,
gl::TextureCapsMap *outTextureCaps, gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions, 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