Commit f7f8c518 by Markus Tavenrath Committed by Commit Bot

Optimize State::syncDirtyObjects

Create a function table for State::syncDirtyObjects to avoid the costly switch and inline calls along the Context::syncDirtyObjects calling hierarchy. Bug: angleproject:2975 Change-Id: I1ec797452af41bc767578e4017c8eccb7d83628b Reviewed-on: https://chromium-review.googlesource.com/c/1340222 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent a1442ecd
...@@ -200,7 +200,7 @@ IterableBitSet<N>::Iterator::Iterator(const std::bitset<N> &bitset) ...@@ -200,7 +200,7 @@ IterableBitSet<N>::Iterator::Iterator(const std::bitset<N> &bitset)
} }
template <size_t N> template <size_t N>
typename IterableBitSet<N>::Iterator &IterableBitSet<N>::Iterator::operator++() ANGLE_INLINE typename IterableBitSet<N>::Iterator &IterableBitSet<N>::Iterator::operator++()
{ {
ASSERT(mBits.any()); ASSERT(mBits.any());
mBits.set(mCurrentBit - mOffset, 0); mBits.set(mCurrentBit - mOffset, 0);
...@@ -446,7 +446,8 @@ BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(b ...@@ -446,7 +446,8 @@ BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(b
} }
template <size_t N, typename BitsT, typename ParamT> template <size_t N, typename BitsT, typename ParamT>
typename BitSetT<N, BitsT, ParamT>::Iterator &BitSetT<N, BitsT, ParamT>::Iterator::operator++() ANGLE_INLINE typename BitSetT<N, BitsT, ParamT>::Iterator &BitSetT<N, BitsT, ParamT>::Iterator::
operator++()
{ {
ASSERT(mBitsCopy.any()); ASSERT(mBitsCopy.any());
mBitsCopy.reset(static_cast<ParamT>(mCurrentBit)); mBitsCopy.reset(static_cast<ParamT>(mCurrentBit));
......
...@@ -3563,11 +3563,6 @@ angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask) ...@@ -3563,11 +3563,6 @@ angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask)
return angle::Result::Continue(); return angle::Result::Continue();
} }
angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask)
{
return mGLState.syncDirtyObjects(this, objectMask);
}
void Context::blitFramebuffer(GLint srcX0, void Context::blitFramebuffer(GLint srcX0,
GLint srcY0, GLint srcY0,
GLint srcX1, GLint srcX1,
......
...@@ -1732,7 +1732,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl ...@@ -1732,7 +1732,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
angle::Result syncState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask); angle::Result syncState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
angle::Result syncDirtyBits(); angle::Result syncDirtyBits();
angle::Result syncDirtyBits(const State::DirtyBits &bitMask); angle::Result syncDirtyBits(const State::DirtyBits &bitMask);
angle::Result syncDirtyObjects(const State::DirtyObjects &objectMask); ANGLE_INLINE angle::Result syncDirtyObjects(const State::DirtyObjects &objectMask)
{
return mGLState.syncDirtyObjects(this, objectMask);
}
angle::Result syncStateForReadPixels(); angle::Result syncStateForReadPixels();
angle::Result syncStateForTexImage(); angle::Result syncStateForTexImage();
angle::Result syncStateForBlit(); angle::Result syncStateForBlit();
......
...@@ -2479,49 +2479,33 @@ void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data) ...@@ -2479,49 +2479,33 @@ void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
} }
} }
angle::Result State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset) angle::Result State::syncReadFramebuffer(const Context *context)
{ {
const DirtyObjects &dirtyObjects = mDirtyObjects & bitset; ASSERT(mReadFramebuffer);
for (auto dirtyObject : dirtyObjects) return mReadFramebuffer->syncState(context);
{ }
switch (dirtyObject)
{
case DIRTY_OBJECT_READ_FRAMEBUFFER:
ASSERT(mReadFramebuffer);
ANGLE_TRY(mReadFramebuffer->syncState(context));
break;
case DIRTY_OBJECT_DRAW_FRAMEBUFFER:
ASSERT(mDrawFramebuffer);
ANGLE_TRY(mDrawFramebuffer->syncState(context));
break;
case DIRTY_OBJECT_VERTEX_ARRAY:
ASSERT(mVertexArray);
ANGLE_TRY(mVertexArray->syncState(context));
break;
case DIRTY_OBJECT_SAMPLERS:
syncSamplers(context);
break;
case DIRTY_OBJECT_PROGRAM_TEXTURES:
ANGLE_TRY(syncProgramTextures(context));
break;
case DIRTY_OBJECT_PROGRAM:
ANGLE_TRY(mProgram->syncState(context));
break;
default:
UNREACHABLE();
break;
}
}
mDirtyObjects &= ~dirtyObjects; angle::Result State::syncWriteFramebuffer(const Context *context)
return angle::Result::Continue(); {
ASSERT(mDrawFramebuffer);
return mDrawFramebuffer->syncState(context);
}
angle::Result State::syncVertexArray(const Context *context)
{
ASSERT(mVertexArray);
return mVertexArray->syncState(context);
} }
void State::syncSamplers(const Context *context) angle::Result State::syncProgram(const Context *context)
{
return mProgram->syncState(context);
}
angle::Result State::syncSamplers(const Context *context)
{ {
if (mDirtySamplers.none()) if (mDirtySamplers.none())
return; return angle::Result::Continue();
// This could be optimized by tracking which samplers are dirty. // This could be optimized by tracking which samplers are dirty.
for (size_t samplerIndex : mDirtySamplers) for (size_t samplerIndex : mDirtySamplers)
...@@ -2534,6 +2518,8 @@ void State::syncSamplers(const Context *context) ...@@ -2534,6 +2518,8 @@ void State::syncSamplers(const Context *context)
} }
mDirtySamplers.reset(); mDirtySamplers.reset();
return angle::Result::Continue();
} }
angle::Result State::syncProgramTextures(const Context *context) angle::Result State::syncProgramTextures(const Context *context)
...@@ -2797,4 +2783,6 @@ AttributesMask State::getAndResetDirtyCurrentValues() const ...@@ -2797,4 +2783,6 @@ AttributesMask State::getAndResetDirtyCurrentValues() const
return retVal; return retVal;
} }
constexpr State::DirtyObjectHandler State::kDirtyObjectHandlers[DIRTY_OBJECT_MAX];
} // namespace gl } // namespace gl
...@@ -483,7 +483,7 @@ class State : angle::NonCopyable ...@@ -483,7 +483,7 @@ class State : angle::NonCopyable
// TODO(jmadill): Consider storing dirty objects in a list instead of by binding. // TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
enum DirtyObjectType enum DirtyObjectType
{ {
DIRTY_OBJECT_READ_FRAMEBUFFER, DIRTY_OBJECT_READ_FRAMEBUFFER = 0,
DIRTY_OBJECT_DRAW_FRAMEBUFFER, DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY, DIRTY_OBJECT_VERTEX_ARRAY,
DIRTY_OBJECT_SAMPLERS, DIRTY_OBJECT_SAMPLERS,
...@@ -551,13 +551,31 @@ class State : angle::NonCopyable ...@@ -551,13 +551,31 @@ class State : angle::NonCopyable
using BufferBindingSetter = void (State::*)(const Context *, Buffer *); using BufferBindingSetter = void (State::*)(const Context *, Buffer *);
private: private:
void syncSamplers(const Context *context);
angle::Result syncProgramTextures(const Context *context);
void unsetActiveTextures(ActiveTextureMask textureMask); void unsetActiveTextures(ActiveTextureMask textureMask);
angle::Result updateActiveTexture(const Context *context, angle::Result updateActiveTexture(const Context *context,
size_t textureIndex, size_t textureIndex,
Texture *texture); Texture *texture);
// Functions to synchronize dirty states
angle::Result syncReadFramebuffer(const Context *context);
angle::Result syncWriteFramebuffer(const Context *context);
angle::Result syncVertexArray(const Context *context);
angle::Result syncSamplers(const Context *context);
angle::Result syncProgramTextures(const Context *context);
angle::Result syncProgram(const Context *context);
using DirtyObjectHandler = angle::Result (State::*)(const Context *context);
static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
&State::syncReadFramebuffer, &State::syncWriteFramebuffer, &State::syncVertexArray,
&State::syncSamplers, &State::syncProgramTextures, &State::syncProgram};
static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 0, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 1, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 2, "check DIRTY_OBJECT_VERTEX_ARRAY index");
static_assert(DIRTY_OBJECT_SAMPLERS == 3, "check DIRTY_OBJECT_SAMPLERS index");
static_assert(DIRTY_OBJECT_PROGRAM_TEXTURES == 4, "check DIRTY_OBJECT_PROGRAM_TEXTURES index");
static_assert(DIRTY_OBJECT_PROGRAM == 5, "check DIRTY_OBJECT_PROGRAM index");
// Dispatch table for buffer update functions. // Dispatch table for buffer update functions.
static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters; static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
...@@ -697,6 +715,20 @@ class State : angle::NonCopyable ...@@ -697,6 +715,20 @@ class State : angle::NonCopyable
ActiveTextureMask mDirtySamplers; ActiveTextureMask mDirtySamplers;
}; };
ANGLE_INLINE angle::Result State::syncDirtyObjects(const Context *context,
const DirtyObjects &bitset)
{
const DirtyObjects &dirtyObjects = mDirtyObjects & bitset;
for (size_t dirtyObject : dirtyObjects)
{
ANGLE_TRY((this->*kDirtyObjectHandlers[dirtyObject])(context));
}
mDirtyObjects &= ~dirtyObjects;
return angle::Result::Continue();
}
} // namespace gl } // namespace gl
#endif // LIBANGLE_STATE_H_ #endif // LIBANGLE_STATE_H_
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