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)
}
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());
mBits.set(mCurrentBit - mOffset, 0);
......@@ -446,7 +446,8 @@ BitSetT<N, BitsT, ParamT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(b
}
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());
mBitsCopy.reset(static_cast<ParamT>(mCurrentBit));
......
......@@ -3563,11 +3563,6 @@ angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask)
return angle::Result::Continue();
}
angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask)
{
return mGLState.syncDirtyObjects(this, objectMask);
}
void Context::blitFramebuffer(GLint srcX0,
GLint srcY0,
GLint srcX1,
......
......@@ -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 syncDirtyBits();
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 syncStateForTexImage();
angle::Result syncStateForBlit();
......
......@@ -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;
for (auto dirtyObject : dirtyObjects)
{
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;
}
}
ASSERT(mReadFramebuffer);
return mReadFramebuffer->syncState(context);
}
mDirtyObjects &= ~dirtyObjects;
return angle::Result::Continue();
angle::Result State::syncWriteFramebuffer(const Context *context)
{
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())
return;
return angle::Result::Continue();
// This could be optimized by tracking which samplers are dirty.
for (size_t samplerIndex : mDirtySamplers)
......@@ -2534,6 +2518,8 @@ void State::syncSamplers(const Context *context)
}
mDirtySamplers.reset();
return angle::Result::Continue();
}
angle::Result State::syncProgramTextures(const Context *context)
......@@ -2797,4 +2783,6 @@ AttributesMask State::getAndResetDirtyCurrentValues() const
return retVal;
}
constexpr State::DirtyObjectHandler State::kDirtyObjectHandlers[DIRTY_OBJECT_MAX];
} // namespace gl
......@@ -483,7 +483,7 @@ class State : angle::NonCopyable
// TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
enum DirtyObjectType
{
DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_READ_FRAMEBUFFER = 0,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY,
DIRTY_OBJECT_SAMPLERS,
......@@ -551,13 +551,31 @@ class State : angle::NonCopyable
using BufferBindingSetter = void (State::*)(const Context *, Buffer *);
private:
void syncSamplers(const Context *context);
angle::Result syncProgramTextures(const Context *context);
void unsetActiveTextures(ActiveTextureMask textureMask);
angle::Result updateActiveTexture(const Context *context,
size_t textureIndex,
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.
static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
......@@ -697,6 +715,20 @@ class State : angle::NonCopyable
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
#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