Commit f38cb6d3 by Jamie Madill Committed by Commit Bot

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: 's avatarGeoff Lang <geofflang@chromium.org>
parent 7818a85c
......@@ -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 @@ angle::Result FramebufferGL::syncState(const gl::Context *context,
}
}
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 @@ bool FramebufferGL::isDefault() const
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)
{
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);
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;
}
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);
const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context);
stateManager->bindFramebuffer(binding, mFramebufferID);
functions->drawBuffers(drawBufferCount, drawBuffers);
}
ASSERT(stateManager->getFramebufferID(angle::FramebufferBindingDraw) == mFramebufferID);
functions->drawBuffers(drawBufferCount, drawBuffers);
}
void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
......
......@@ -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 @@ class FramebufferGL : public FramebufferImpl
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 @@ class FramebufferGL : public FramebufferImpl
GLubyte *pixels,
bool readLastRowSeparately) const;
void maskOutInactiveOutputDrawBuffersImpl(const gl::Context *context,
gl::DrawBufferMask targetAppliedDrawBuffers);
GLuint mFramebufferID;
bool mIsDefault;
......
......@@ -247,6 +247,71 @@ angle::Result RendererGL::finish()
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 @@ angle::Result RendererGL::drawArrays(const gl::Context *context,
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 @@ angle::Result RendererGL::drawArraysInstanced(const gl::Context *context,
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 @@ angle::Result RendererGL::drawElements(const gl::Context *context,
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 @@ angle::Result RendererGL::drawElementsInstanced(const gl::Context *context,
}
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 @@ angle::Result RendererGL::drawRangeElements(const gl::Context *context,
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 @@ angle::Result RendererGL::drawArraysIndirect(const gl::Context *context,
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 @@ angle::Result RendererGL::drawElementsIndirect(const gl::Context *context,
GLenum type,
const void *indirect)
{
ANGLE_TRY(mStateManager->setDrawIndirectState(context));
ANGLE_TRY(setDrawIndirectState(context));
mFunctions->drawElementsIndirect(ToGLenum(mode), type, indirect);
return angle::Result::Continue();
}
......
......@@ -192,6 +192,20 @@ class RendererGL : angle::NonCopyable
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;
......
......@@ -161,8 +161,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mPathStencilMask(std::numeric_limits<GLuint>::max()),
mIsSideBySideDrawFramebuffer(false),
mIsMultiviewEnabled(extensions.multiview),
mLocalDirtyBits(),
mMultiviewDirtyBits()
mLocalDirtyBits()
{
ASSERT(mFunctions);
ASSERT(extensions.maxViews >= 1u);
......@@ -674,51 +673,6 @@ void StateManagerGL::endQuery(gl::QueryType type, QueryGL *queryObject, GLuint q
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 @@ void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
}
}
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::setViewportArrayv(GLuint first, const std::vector<gl::Recta
}
}
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 @@ void StateManagerGL::syncState(const gl::Context *context,
// 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;
......
......@@ -77,7 +77,6 @@ class StateManagerGL final : angle::NonCopyable
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 @@ class StateManagerGL final : angle::NonCopyable
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 @@ class StateManagerGL final : angle::NonCopyable
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 @@ class StateManagerGL final : angle::NonCopyable
}
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 @@ class StateManagerGL final : angle::NonCopyable
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 @@ class StateManagerGL final : angle::NonCopyable
gl::State::DirtyBits mLocalDirtyBits;
gl::AttributesMask mLocalDirtyCurrentValues;
// ANGLE_multiview dirty bits.
angle::BitSet<MULTIVIEW_DIRTY_BIT_MAX> mMultiviewDirtyBits;
};
} // namespace rx
......
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