StateManagerGL: Optimize state application.
There are two main optimizations:
1. Inline setDraw*State and maskOutInactiveOutputDrawBuffers.
2. Remove Multiview dirty bits.
The first change is a refactoring only. It moves the code around a bit
so we can hit a fast path and never have to push/pop registers. The
second change is also a no-op since the multiview dirty bits were made
redundant.
Improves performance in the command buffer perftests by 1-5%.
Bug: angleproject:2877
Change-Id: I1632a838371ec8b85c2e06b3b86f08727ca9dacf
Reviewed-on: https://chromium-review.googlesource.com/c/1293629
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index a5a64cd..97a8081 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -10,7 +10,6 @@
#include "common/bitset_utils.h"
#include "common/debug.h"
-#include "libANGLE/Context.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/State.h"
#include "libANGLE/angletypes.h"
@@ -714,12 +713,11 @@
}
}
- if (attachment)
+ if (attachment && mState.id() == context->getGLState().getDrawFramebuffer()->id())
{
const bool isSideBySide =
(attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
stateManager->setSideBySide(isSideBySide);
- stateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
getState());
}
@@ -737,32 +735,28 @@
return mIsDefault;
}
-void FramebufferGL::maskOutInactiveOutputDrawBuffers(const gl::Context *context,
- GLenum binding,
- DrawBufferMask maxSet)
+void FramebufferGL::maskOutInactiveOutputDrawBuffersImpl(const gl::Context *context,
+ DrawBufferMask targetAppliedDrawBuffers)
{
- auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
- if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
+ ASSERT(mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers);
+ mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
+
+ const auto &stateDrawBuffers = mState.getDrawBufferStates();
+ GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
+ ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
{
- mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
-
- const auto &stateDrawBuffers = mState.getDrawBufferStates();
- GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
- ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
-
- GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
- for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
- {
- drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
- }
-
- const FunctionsGL *functions = GetFunctionsGL(context);
- StateManagerGL *stateManager = GetStateManagerGL(context);
-
- stateManager->bindFramebuffer(binding, mFramebufferID);
- functions->drawBuffers(drawBufferCount, drawBuffers);
+ drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
}
+
+ const FunctionsGL *functions = GetFunctionsGL(context);
+ StateManagerGL *stateManager = GetStateManagerGL(context);
+
+ ASSERT(stateManager->getFramebufferID(angle::FramebufferBindingDraw) == mFramebufferID);
+ functions->drawBuffers(drawBufferCount, drawBuffers);
}
void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.h b/src/libANGLE/renderer/gl/FramebufferGL.h
index c6cc286..166f6a6 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.h
+++ b/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -9,6 +9,7 @@
#ifndef LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
#define LIBANGLE_RENDERER_GL_FRAMEBUFFERGL_H_
+#include "libANGLE/Context.h"
#include "libANGLE/renderer/FramebufferImpl.h"
namespace rx
@@ -85,9 +86,19 @@
GLuint getFramebufferID() const;
bool isDefault() const;
- void maskOutInactiveOutputDrawBuffers(const gl::Context *context,
- GLenum binding,
- gl::DrawBufferMask maxSet);
+ ANGLE_INLINE void maskOutInactiveOutputDrawBuffers(const gl::Context *context)
+ {
+ ASSERT(context->getExtensions().webglCompatibility);
+
+ const gl::DrawBufferMask &maxSet =
+ context->getGLState().getProgram()->getActiveOutputVariables();
+
+ gl::DrawBufferMask targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
+ if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
+ {
+ maskOutInactiveOutputDrawBuffersImpl(context, targetAppliedDrawBuffers);
+ }
+ }
private:
void syncClearState(const gl::Context *context, GLbitfield mask);
@@ -113,6 +124,9 @@
GLubyte *pixels,
bool readLastRowSeparately) const;
+ void maskOutInactiveOutputDrawBuffersImpl(const gl::Context *context,
+ gl::DrawBufferMask targetAppliedDrawBuffers);
+
GLuint mFramebufferID;
bool mIsDefault;
diff --git a/src/libANGLE/renderer/gl/RendererGL.cpp b/src/libANGLE/renderer/gl/RendererGL.cpp
index a7e5807..6c8b76f 100644
--- a/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -247,6 +247,71 @@
return angle::Result::Continue();
}
+ANGLE_INLINE angle::Result RendererGL::setDrawArraysState(const gl::Context *context,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ if (context->getStateCache().hasAnyActiveClientAttrib())
+ {
+ const gl::State &glState = context->getGLState();
+ const gl::Program *program = glState.getProgram();
+ const gl::VertexArray *vao = glState.getVertexArray();
+ const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+ ANGLE_TRY(vaoGL->syncClientSideData(context, program->getActiveAttribLocationsMask(), first,
+ count, instanceCount));
+ }
+
+ if (context->getExtensions().webglCompatibility)
+ {
+ const gl::State &glState = context->getGLState();
+ FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(glState.getDrawFramebuffer());
+ framebufferGL->maskOutInactiveOutputDrawBuffers(context);
+ }
+
+ return angle::Result::Continue();
+}
+
+ANGLE_INLINE angle::Result RendererGL::setDrawElementsState(const gl::Context *context,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instanceCount,
+ const void **outIndices)
+{
+ const gl::State &glState = context->getGLState();
+
+ const gl::Program *program = glState.getProgram();
+
+ const gl::VertexArray *vao = glState.getVertexArray();
+ const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+
+ ANGLE_TRY(vaoGL->syncDrawElementsState(context, program->getActiveAttribLocationsMask(), count,
+ type, indices, instanceCount,
+ glState.isPrimitiveRestartEnabled(), outIndices));
+
+ if (context->getExtensions().webglCompatibility)
+ {
+ FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(glState.getDrawFramebuffer());
+ framebufferGL->maskOutInactiveOutputDrawBuffers(context);
+ }
+
+ return angle::Result::Continue();
+}
+
+ANGLE_INLINE angle::Result RendererGL::setDrawIndirectState(const gl::Context *context)
+{
+ if (context->getExtensions().webglCompatibility)
+ {
+ const gl::State &glState = context->getGLState();
+ FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(glState.getDrawFramebuffer());
+ framebufferGL->maskOutInactiveOutputDrawBuffers(context);
+ }
+
+ return angle::Result::Continue();
+}
+
angle::Result RendererGL::drawArrays(const gl::Context *context,
gl::PrimitiveMode mode,
GLint first,
@@ -256,7 +321,7 @@
const bool usesMultiview = program->usesMultiview();
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
- ANGLE_TRY(mStateManager->setDrawArraysState(context, first, count, instanceCount));
+ ANGLE_TRY(setDrawArraysState(context, first, count, instanceCount));
if (!usesMultiview)
{
mFunctions->drawArrays(ToGLenum(mode), first, count);
@@ -281,7 +346,7 @@
adjustedInstanceCount *= program->getNumViews();
}
- ANGLE_TRY(mStateManager->setDrawArraysState(context, first, count, adjustedInstanceCount));
+ ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
mFunctions->drawArraysInstanced(ToGLenum(mode), first, count, adjustedInstanceCount);
return angle::Result::Continue();
}
@@ -297,8 +362,7 @@
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const void *drawIndexPtr = nullptr;
- ANGLE_TRY(mStateManager->setDrawElementsState(context, count, type, indices, instanceCount,
- &drawIndexPtr));
+ ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
if (!usesMultiview)
{
mFunctions->drawElements(ToGLenum(mode), count, type, drawIndexPtr);
@@ -325,8 +389,8 @@
}
const void *drawIndexPointer = nullptr;
- ANGLE_TRY(mStateManager->setDrawElementsState(context, count, type, indices,
- adjustedInstanceCount, &drawIndexPointer));
+ ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
+ &drawIndexPointer));
mFunctions->drawElementsInstanced(ToGLenum(mode), count, type, drawIndexPointer,
adjustedInstanceCount);
return angle::Result::Continue();
@@ -345,8 +409,8 @@
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const void *drawIndexPointer = nullptr;
- ANGLE_TRY(mStateManager->setDrawElementsState(context, count, type, indices, instanceCount,
- &drawIndexPointer));
+ ANGLE_TRY(
+ setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
if (!usesMultiview)
{
mFunctions->drawRangeElements(ToGLenum(mode), start, end, count, type, drawIndexPointer);
@@ -363,7 +427,7 @@
gl::PrimitiveMode mode,
const void *indirect)
{
- ANGLE_TRY(mStateManager->setDrawIndirectState(context));
+ ANGLE_TRY(setDrawIndirectState(context));
mFunctions->drawArraysIndirect(ToGLenum(mode), indirect);
return angle::Result::Continue();
}
@@ -373,7 +437,7 @@
GLenum type,
const void *indirect)
{
- ANGLE_TRY(mStateManager->setDrawIndirectState(context));
+ ANGLE_TRY(setDrawIndirectState(context));
mFunctions->drawElementsIndirect(ToGLenum(mode), type, indirect);
return angle::Result::Continue();
}
diff --git a/src/libANGLE/renderer/gl/RendererGL.h b/src/libANGLE/renderer/gl/RendererGL.h
index 0f1b02a..7d4b035 100644
--- a/src/libANGLE/renderer/gl/RendererGL.h
+++ b/src/libANGLE/renderer/gl/RendererGL.h
@@ -192,6 +192,20 @@
gl::Extensions *outExtensions,
gl::Limitations *outLimitations) const;
+ angle::Result setDrawArraysState(const gl::Context *context,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount);
+
+ angle::Result setDrawElementsState(const gl::Context *context,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instanceCount,
+ const void **outIndices);
+
+ angle::Result setDrawIndirectState(const gl::Context *context);
+
mutable gl::Version mMaxSupportedESVersion;
std::unique_ptr<FunctionsGL> mFunctions;
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index f442a1d..1e06290 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -161,8 +161,7 @@
mPathStencilMask(std::numeric_limits<GLuint>::max()),
mIsSideBySideDrawFramebuffer(false),
mIsMultiviewEnabled(extensions.multiview),
- mLocalDirtyBits(),
- mMultiviewDirtyBits()
+ mLocalDirtyBits()
{
ASSERT(mFunctions);
ASSERT(extensions.maxViews >= 1u);
@@ -674,51 +673,6 @@
mFunctions->endQuery(ToGLenum(type));
}
-angle::Result StateManagerGL::setDrawArraysState(const gl::Context *context,
- GLint first,
- GLsizei count,
- GLsizei instanceCount)
-{
- if (context->getStateCache().hasAnyActiveClientAttrib())
- {
- const gl::State &glState = context->getGLState();
- const gl::Program *program = glState.getProgram();
- const gl::VertexArray *vao = glState.getVertexArray();
- const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
-
- ANGLE_TRY(vaoGL->syncClientSideData(context, program->getActiveAttribLocationsMask(), first,
- count, instanceCount));
- }
-
- return setGenericDrawState(context);
-}
-
-angle::Result StateManagerGL::setDrawElementsState(const gl::Context *context,
- GLsizei count,
- GLenum type,
- const void *indices,
- GLsizei instanceCount,
- const void **outIndices)
-{
- const gl::State &glState = context->getGLState();
-
- const gl::Program *program = glState.getProgram();
-
- const gl::VertexArray *vao = glState.getVertexArray();
- const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
-
- ANGLE_TRY(vaoGL->syncDrawElementsState(context, program->getActiveAttribLocationsMask(), count,
- type, indices, instanceCount,
- glState.isPrimitiveRestartEnabled(), outIndices));
-
- return setGenericDrawState(context);
-}
-
-angle::Result StateManagerGL::setDrawIndirectState(const gl::Context *context)
-{
- return setGenericDrawState(context);
-}
-
void StateManagerGL::updateDrawIndirectBufferBinding(const gl::Context *context)
{
gl::Buffer *drawIndirectBuffer =
@@ -1016,26 +970,6 @@
}
}
-angle::Result StateManagerGL::setGenericDrawState(const gl::Context *context)
-{
- if (context->getExtensions().webglCompatibility)
- {
- const gl::State &glState = context->getGLState();
- FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(glState.getDrawFramebuffer());
- auto activeOutputs = glState.getProgram()->getState().getActiveOutputVariables();
- framebufferGL->maskOutInactiveOutputDrawBuffers(context, GL_DRAW_FRAMEBUFFER,
- activeOutputs);
- }
-
- ASSERT(
- mFramebuffers[angle::FramebufferBindingDraw] ==
- GetImplAs<FramebufferGL>(context->getGLState().getDrawFramebuffer())->getFramebufferID());
- ASSERT(mVAO ==
- GetImplAs<VertexArrayGL>(context->getGLState().getVertexArray())->getVertexArrayID());
-
- return angle::Result::Continue();
-}
-
void StateManagerGL::setAttributeCurrentData(size_t index,
const gl::VertexAttribCurrentValueData &data)
{
@@ -1152,30 +1086,11 @@
}
}
-void StateManagerGL::setViewportOffsets(const std::vector<gl::Offset> &viewportOffsets)
-{
- if (!std::equal(viewportOffsets.cbegin(), viewportOffsets.cend(), mViewportOffsets.cbegin()))
- {
- std::copy(viewportOffsets.begin(), viewportOffsets.end(), mViewportOffsets.begin());
-
- const std::vector<gl::Rectangle> &viewportArray =
- ApplyOffsets(mViewports[0], viewportOffsets);
- setViewportArrayv(0u, viewportArray);
-
- const std::vector<gl::Rectangle> &scissorArray =
- ApplyOffsets(mScissors[0], viewportOffsets);
- setScissorArrayv(0u, scissorArray);
-
- mMultiviewDirtyBits.set(MULTIVIEW_DIRTY_BIT_VIEWPORT_OFFSETS);
- }
-}
-
void StateManagerGL::setSideBySide(bool isSideBySide)
{
if (mIsSideBySideDrawFramebuffer != isSideBySide)
{
mIsSideBySideDrawFramebuffer = isSideBySide;
- mMultiviewDirtyBits.set(MULTIVIEW_DIRTY_BIT_SIDE_BY_SIDE_LAYOUT);
}
}
@@ -1680,47 +1595,18 @@
// When a new draw framebuffer is bound, we have to mark the layout, viewport offsets,
// scissor test, scissor and viewport rectangle bits as dirty because it could be a
// transition from or to a side-by-side draw framebuffer.
- mMultiviewDirtyBits.set(MULTIVIEW_DIRTY_BIT_SIDE_BY_SIDE_LAYOUT);
- mMultiviewDirtyBits.set(MULTIVIEW_DIRTY_BIT_VIEWPORT_OFFSETS);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_SCISSOR);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_VIEWPORT);
- }
- }
- // Iterate over and resolve multi-view dirty bits.
- if (mMultiviewDirtyBits.any())
- {
- for (auto dirtyBit : mMultiviewDirtyBits)
- {
- switch (dirtyBit)
+ const gl::FramebufferAttachment *attachment =
+ state.getDrawFramebuffer()->getFirstNonNullAttachment();
+ if (attachment)
{
- case MULTIVIEW_DIRTY_BIT_SIDE_BY_SIDE_LAYOUT:
- {
- const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();
- ASSERT(drawFramebuffer != nullptr);
- setSideBySide(drawFramebuffer->getMultiviewLayout() ==
- GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
- }
- break;
- case MULTIVIEW_DIRTY_BIT_VIEWPORT_OFFSETS:
- {
- const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();
- ASSERT(drawFramebuffer != nullptr);
- const std::vector<gl::Offset> *attachmentViewportOffsets =
- drawFramebuffer->getViewportOffsets();
- const std::vector<gl::Offset> &viewportOffsets =
- attachmentViewportOffsets != nullptr
- ? *attachmentViewportOffsets
- : gl::FramebufferAttachment::GetDefaultViewportOffsetVector();
- setViewportOffsets(viewportOffsets);
- }
- break;
- default:
- UNREACHABLE();
+ setSideBySide(attachment->getMultiviewLayout() ==
+ GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
}
}
- mMultiviewDirtyBits.reset();
}
const gl::State::DirtyBits &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h
index 47b8b9d..de0cf86 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -77,7 +77,6 @@
void onTransformFeedbackStateChange();
void beginQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId);
void endQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId);
- void onBeginQuery(QueryGL *query);
void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data);
@@ -90,7 +89,6 @@
void setViewportArrayv(GLuint first, const std::vector<gl::Rectangle> &viewports);
void setDepthRange(float near, float far);
- void setViewportOffsets(const std::vector<gl::Offset> &kviewportOffsets);
void setSideBySide(bool isSideBySide);
void setBlendEnabled(bool enabled);
@@ -153,18 +151,6 @@
void setPathRenderingProjectionMatrix(const GLfloat *m);
void setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask);
- angle::Result setDrawArraysState(const gl::Context *context,
- GLint first,
- GLsizei count,
- GLsizei instanceCount);
- angle::Result setDrawElementsState(const gl::Context *context,
- GLsizei count,
- GLenum type,
- const void *indices,
- GLsizei instanceCount,
- const void **outIndices);
- angle::Result setDrawIndirectState(const gl::Context *context);
-
void pauseTransformFeedback();
angle::Result pauseAllQueries(const gl::Context *context);
angle::Result pauseQuery(const gl::Context *context, gl::QueryType type);
@@ -187,11 +173,12 @@
}
GLuint getVertexArrayID() const { return mVAO; }
+ GLuint getFramebufferID(angle::FramebufferBinding binding) const
+ {
+ return mFramebuffers[binding];
+ }
private:
- // Set state that's common among draw commands.
- angle::Result setGenericDrawState(const gl::Context *context);
-
void setTextureCubemapSeamlessEnabled(bool enabled);
void applyViewportOffsetsAndSetScissors(const gl::Rectangle &scissor,
@@ -216,13 +203,6 @@
const gl::Program *program,
const gl::FramebufferState &drawFramebufferState) const;
- enum MultiviewDirtyBitType
- {
- MULTIVIEW_DIRTY_BIT_SIDE_BY_SIDE_LAYOUT,
- MULTIVIEW_DIRTY_BIT_VIEWPORT_OFFSETS,
- MULTIVIEW_DIRTY_BIT_MAX
- };
-
const FunctionsGL *mFunctions;
GLuint mProgram;
@@ -370,9 +350,6 @@
gl::State::DirtyBits mLocalDirtyBits;
gl::AttributesMask mLocalDirtyCurrentValues;
-
- // ANGLE_multiview dirty bits.
- angle::BitSet<MULTIVIEW_DIRTY_BIT_MAX> mMultiviewDirtyBits;
};
} // namespace rx