Commit c9d442d7 by Jamie Madill

Sync dirty objects at the GL layer.

The dirty bit system currently puts dirty objects in line with the rest of the dirty state. This means at the Renderer level, the sync manager code would call back to the GL layer to sync the specific objects that are dirty. This is a bit of a layering violation (impl layer mutating top-level objects) and also a bit of repeated boiler- plate code. Fix this by treating dirty objects in a separate dirty bit set, called the dirty objects. This also has the benefit of allowing us to re- implement the dirty object set at a later date, if we want to store them in a list, or other structure. Also don't skip the state sync at the GL level if there are no GL dirty bits. The Impl might have some dirty bits locally, and it's better to call syncState and do the no-op check in the Impl than it is to also sync local state at every sync point (draw call, read, etc) in each Impl. BUG=angleproject:1260 Change-Id: Id5d4beb2a1c4e3ad351edf54e3f32e828d5f5da3 Reviewed-on: https://chromium-review.googlesource.com/318790Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 6fd7472f
...@@ -1919,21 +1919,19 @@ void Context::initCaps(GLuint clientVersion) ...@@ -1919,21 +1919,19 @@ void Context::initCaps(GLuint clientVersion)
void Context::syncRendererState() void Context::syncRendererState()
{ {
const State::DirtyBits &dirtyBits = mState.getDirtyBits(); const State::DirtyBits &dirtyBits = mState.getDirtyBits();
if (dirtyBits.any()) mRenderer->syncState(mState, dirtyBits);
{ mState.clearDirtyBits();
mRenderer->syncState(mState, dirtyBits); mState.syncDirtyObjects();
mState.clearDirtyBits();
}
} }
void Context::syncRendererState(const State::DirtyBits &bitMask) void Context::syncRendererState(const State::DirtyBits &bitMask)
{ {
const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask); const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask);
if (dirtyBits.any()) mRenderer->syncState(mState, dirtyBits);
{ mState.clearDirtyBits(dirtyBits);
mRenderer->syncState(mState, dirtyBits);
mState.clearDirtyBits(dirtyBits); // TODO(jmadill): Filter objects by bitMask somehow?
} mState.syncDirtyObjects();
} }
void Context::blitFramebuffer(GLint srcX0, void Context::blitFramebuffer(GLint srcX0,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "common/BitSetIterator.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
...@@ -901,7 +902,11 @@ void State::setVertexArrayBinding(VertexArray *vertexArray) ...@@ -901,7 +902,11 @@ void State::setVertexArrayBinding(VertexArray *vertexArray)
{ {
mVertexArray = vertexArray; mVertexArray = vertexArray;
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_OBJECT);
if (mVertexArray && mVertexArray->hasAnyDirtyBit())
{
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
} }
GLuint State::getVertexArrayId() const GLuint State::getVertexArrayId() const
...@@ -922,7 +927,7 @@ bool State::removeVertexArrayBinding(GLuint vertexArray) ...@@ -922,7 +927,7 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
{ {
mVertexArray = NULL; mVertexArray = NULL;
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_OBJECT); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
return true; return true;
} }
...@@ -1098,7 +1103,7 @@ void State::detachBuffer(GLuint bufferName) ...@@ -1098,7 +1103,7 @@ void State::detachBuffer(GLuint bufferName)
void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
{ {
getVertexArray()->enableAttribute(attribNum, enabled); getVertexArray()->enableAttribute(attribNum, enabled);
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_OBJECT); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
void State::setVertexAttribf(GLuint index, const GLfloat values[4]) void State::setVertexAttribf(GLuint index, const GLfloat values[4])
...@@ -1132,13 +1137,13 @@ void State::setVertexAttribState(unsigned int attribNum, ...@@ -1132,13 +1137,13 @@ void State::setVertexAttribState(unsigned int attribNum,
const void *pointer) const void *pointer)
{ {
getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_OBJECT); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
void State::setVertexAttribDivisor(GLuint index, GLuint divisor) void State::setVertexAttribDivisor(GLuint index, GLuint divisor)
{ {
getVertexArray()->setVertexAttribDivisor(index, divisor); getVertexArray()->setVertexAttribDivisor(index, divisor);
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_OBJECT); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
...@@ -1710,4 +1715,34 @@ bool State::hasMappedBuffer(GLenum target) const ...@@ -1710,4 +1715,34 @@ bool State::hasMappedBuffer(GLenum target) const
} }
} }
void State::syncDirtyObjects()
{
if (!mDirtyObjects.any())
return;
for (auto dirtyObject : angle::IterateBitSet(mDirtyObjects))
{
switch (dirtyObject)
{
case DIRTY_OBJECT_READ_FRAMEBUFFER:
// TODO(jmadill): implement this
break;
case DIRTY_OBJECT_DRAW_FRAMEBUFFER:
// TODO(jmadill): implement this
break;
case DIRTY_OBJECT_VERTEX_ARRAY:
mVertexArray->syncImplState();
break;
case DIRTY_OBJECT_PROGRAM:
// TODO(jmadill): implement this
break;
default:
UNREACHABLE();
break;
}
}
mDirtyObjects.reset();
} }
} // namespace gl
...@@ -328,26 +328,38 @@ class State : angle::NonCopyable ...@@ -328,26 +328,38 @@ class State : angle::NonCopyable
DIRTY_BIT_GENERATE_MIPMAP_HINT, DIRTY_BIT_GENERATE_MIPMAP_HINT,
DIRTY_BIT_SHADER_DERIVATIVE_HINT, DIRTY_BIT_SHADER_DERIVATIVE_HINT,
DIRTY_BIT_READ_FRAMEBUFFER_BINDING, DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
DIRTY_BIT_READ_FRAMEBUFFER_OBJECT,
DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING, DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
DIRTY_BIT_DRAW_FRAMEBUFFER_OBJECT,
DIRTY_BIT_RENDERBUFFER_BINDING, DIRTY_BIT_RENDERBUFFER_BINDING,
DIRTY_BIT_VERTEX_ARRAY_BINDING, DIRTY_BIT_VERTEX_ARRAY_BINDING,
DIRTY_BIT_VERTEX_ARRAY_OBJECT,
DIRTY_BIT_PROGRAM_BINDING, DIRTY_BIT_PROGRAM_BINDING,
DIRTY_BIT_PROGRAM_OBJECT,
DIRTY_BIT_CURRENT_VALUE_0, DIRTY_BIT_CURRENT_VALUE_0,
DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS, DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX, DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX,
DIRTY_BIT_MAX = DIRTY_BIT_INVALID, DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
}; };
// TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
enum DirtyObjectType
{
DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY,
DIRTY_OBJECT_PROGRAM,
DIRTY_OBJECT_UNKNOWN,
DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
};
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits; typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
const DirtyBits &getDirtyBits() const { return mDirtyBits; } const DirtyBits &getDirtyBits() const { return mDirtyBits; }
void clearDirtyBits() { mDirtyBits.reset(); } void clearDirtyBits() { mDirtyBits.reset(); }
void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; } void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
void setAllDirtyBits() { mDirtyBits.set(); } void setAllDirtyBits() { mDirtyBits.set(); }
typedef std::bitset<DIRTY_OBJECT_MAX> DirtyObjects;
void clearDirtyObjects() { mDirtyObjects.reset(); }
void setAllDirtyObjects() { mDirtyObjects.set(); }
void syncDirtyObjects();
// Dirty bit masks // Dirty bit masks
const DirtyBits &unpackStateBitMask() const { return mUnpackStateBitMask; } const DirtyBits &unpackStateBitMask() const { return mUnpackStateBitMask; }
const DirtyBits &packStateBitMask() const { return mPackStateBitMask; } const DirtyBits &packStateBitMask() const { return mPackStateBitMask; }
...@@ -430,6 +442,8 @@ class State : angle::NonCopyable ...@@ -430,6 +442,8 @@ class State : angle::NonCopyable
DirtyBits mPackStateBitMask; DirtyBits mPackStateBitMask;
DirtyBits mClearStateBitMask; DirtyBits mClearStateBitMask;
DirtyBits mBlitStateBitMask; DirtyBits mBlitStateBitMask;
DirtyObjects mDirtyObjects;
}; };
} }
......
...@@ -109,6 +109,7 @@ class VertexArray final : public LabeledObject ...@@ -109,6 +109,7 @@ class VertexArray final : public LabeledObject
typedef std::bitset<DIRTY_BIT_MAX> DirtyBits; typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
void syncImplState(); void syncImplState();
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
private: private:
GLuint mId; GLuint mId;
......
...@@ -111,6 +111,11 @@ void StateManager11::setViewportBounds(const int width, const int height) ...@@ -111,6 +111,11 @@ void StateManager11::setViewportBounds(const int width, const int height)
void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
{ {
if (!dirtyBits.any())
{
return;
}
for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits)) for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits))
{ {
switch (dirtyBit) switch (dirtyBit)
......
...@@ -109,6 +109,11 @@ void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized, ...@@ -109,6 +109,11 @@ void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized,
void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
{ {
if (!dirtyBits.any())
{
return;
}
for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
{ {
switch (dirtyBit) switch (dirtyBit)
......
...@@ -1274,10 +1274,17 @@ void StateManagerGL::setClearStencil(GLint clearStencil) ...@@ -1274,10 +1274,17 @@ void StateManagerGL::setClearStencil(GLint clearStencil)
} }
} }
void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits)
{ {
const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
if (!glAndLocalDirtyBits.any())
{
return;
}
// TODO(jmadill): Investigate only syncing vertex state for active attributes // TODO(jmadill): Investigate only syncing vertex state for active attributes
for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits)) for (auto dirtyBit : angle::IterateBitSet(glAndLocalDirtyBits))
{ {
switch (dirtyBit) switch (dirtyBit)
{ {
...@@ -1469,30 +1476,18 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit ...@@ -1469,30 +1476,18 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit
case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING: case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
// TODO(jmadill): implement this // TODO(jmadill): implement this
break; break;
case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_OBJECT:
// TODO(jmadill): implement this
break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
// TODO(jmadill): implement this // TODO(jmadill): implement this
break; break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_OBJECT:
// TODO(jmadill): implement this
break;
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
// TODO(jmadill): implement this // TODO(jmadill): implement this
break; break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
// TODO(jmadill): implement this // TODO(jmadill): implement this
break; break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_OBJECT:
state.getVertexArray()->syncImplState();
break;
case gl::State::DIRTY_BIT_PROGRAM_BINDING: case gl::State::DIRTY_BIT_PROGRAM_BINDING:
// TODO(jmadill): implement this // TODO(jmadill): implement this
break; break;
case gl::State::DIRTY_BIT_PROGRAM_OBJECT:
// TODO(jmadill): implement this
break;
default: default:
{ {
ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
......
...@@ -135,7 +135,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -135,7 +135,7 @@ class StateManagerGL final : angle::NonCopyable
GLsizei instanceCount, GLsizei instanceCount,
const GLvoid **outIndices); const GLvoid **outIndices);
void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); void syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits);
private: private:
gl::Error setGenericDrawState(const gl::Data &data); gl::Error setGenericDrawState(const gl::Data &data);
......
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