Commit 132d15c2 by Jamie Madill

Clear uncleared textures as a dirty object.

This removes the check for robust resource init from prepareForDraw. It should improve performance more when WebGL compatiblity is enabled. Also inlines Context::syncDirtyBits and Context::prepareForDraw. Reduces CPU overhead in all draw and dispatch calls up to 5%. Bug: angleproject:2966 Change-Id: I7e9009a501c0331a6140bc78678aef27e38c3df2 Reviewed-on: https://chromium-review.googlesource.com/c/1347453Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 9092bdc7
......@@ -3476,10 +3476,13 @@ void Context::updateCaps()
mThreadPool = angle::WorkerThreadPool::Create(mExtensions.parallelShaderCompile);
// Reinitialize some dirty bits that depend on extensions.
mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS,
mGLState.isRobustResourceInitEnabled());
mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS,
mGLState.isRobustResourceInitEnabled());
bool robustInit = mGLState.isRobustResourceInitEnabled();
mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS, robustInit);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT, robustInit);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT, robustInit);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS, robustInit);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT, robustInit);
mComputeDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT, robustInit);
// Reinitialize state cache after extension changes.
mStateCache.initialize(this);
......@@ -3515,7 +3518,28 @@ bool Context::noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei insta
return (instanceCount == 0) || noopDraw(mode, count);
}
angle::Result Context::prepareForDraw(PrimitiveMode mode)
ANGLE_INLINE angle::Result Context::syncDirtyBits()
{
const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
ANGLE_TRY(mImplementation->syncState(this, dirtyBits, mAllDirtyBits));
mGLState.clearDirtyBits();
return angle::Result::Continue();
}
ANGLE_INLINE angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask)
{
const State::DirtyBits &dirtyBits = (mGLState.getDirtyBits() & bitMask);
ANGLE_TRY(mImplementation->syncState(this, dirtyBits, bitMask));
mGLState.clearDirtyBits(dirtyBits);
return angle::Result::Continue();
}
ANGLE_INLINE angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask)
{
return mGLState.syncDirtyObjects(this, objectMask);
}
ANGLE_INLINE angle::Result Context::prepareForDraw(PrimitiveMode mode)
{
if (mGLES1Renderer)
{
......@@ -3523,15 +3547,9 @@ angle::Result Context::prepareForDraw(PrimitiveMode mode)
}
ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects));
if (isRobustResourceInitEnabled())
{
ANGLE_TRY(mGLState.clearUnclearedActiveTextures(this));
ASSERT(!mGLState.getDrawFramebuffer()->hasResourceThatNeedsInit());
}
ANGLE_TRY(syncDirtyBits());
return angle::Result::Continue();
ASSERT(!isRobustResourceInitEnabled() ||
!mGLState.getDrawFramebuffer()->hasResourceThatNeedsInit());
return syncDirtyBits();
}
angle::Result Context::prepareForClear(GLbitfield mask)
......@@ -3551,6 +3569,12 @@ angle::Result Context::prepareForClearBuffer(GLenum buffer, GLint drawbuffer)
return angle::Result::Continue();
}
ANGLE_INLINE angle::Result Context::prepareForDispatch()
{
ANGLE_TRY(syncDirtyObjects(mComputeDirtyObjects));
return syncDirtyBits(mComputeDirtyBits);
}
angle::Result Context::syncState(const State::DirtyBits &bitMask,
const State::DirtyObjects &objectMask)
{
......@@ -3559,22 +3583,6 @@ angle::Result Context::syncState(const State::DirtyBits &bitMask,
return angle::Result::Continue();
}
angle::Result Context::syncDirtyBits()
{
const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
ANGLE_TRY(mImplementation->syncState(this, dirtyBits, mAllDirtyBits));
mGLState.clearDirtyBits();
return angle::Result::Continue();
}
angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask)
{
const State::DirtyBits &dirtyBits = (mGLState.getDirtyBits() & bitMask);
ANGLE_TRY(mImplementation->syncState(this, dirtyBits, bitMask));
mGLState.clearDirtyBits(dirtyBits);
return angle::Result::Continue();
}
void Context::blitFramebuffer(GLint srcX0,
GLint srcY0,
GLint srcX1,
......@@ -5330,18 +5338,6 @@ bool Context::getZeroFilledBuffer(size_t requstedSizeBytes,
return mZeroFilledBuffer.getInitialized(requstedSizeBytes, zeroBufferOut, 0);
}
angle::Result Context::prepareForDispatch()
{
ANGLE_TRY(syncDirtyObjects(mComputeDirtyObjects));
if (isRobustResourceInitEnabled())
{
ANGLE_TRY(mGLState.clearUnclearedActiveTextures(this));
}
return syncDirtyBits(mComputeDirtyBits);
}
void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
{
if (numGroupsX == 0u || numGroupsY == 0u || numGroupsZ == 0u)
......
......@@ -1743,10 +1743,7 @@ 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_INLINE angle::Result syncDirtyObjects(const State::DirtyObjects &objectMask)
{
return mGLState.syncDirtyObjects(this, objectMask);
}
angle::Result syncDirtyObjects(const State::DirtyObjects &objectMask);
angle::Result syncStateForReadPixels();
angle::Result syncStateForTexImage();
angle::Result syncStateForBlit();
......
......@@ -220,8 +220,6 @@ State::State(bool debug,
mVertexArray(nullptr),
mActiveSampler(0),
mActiveTexturesCache{},
mCachedTexturesInitState(InitState::MayNeedInit),
mCachedImageTexturesInitState(InitState::MayNeedInit),
mPrimitiveRestart(false),
mDebug(debug),
mMultiSampling(false),
......@@ -330,8 +328,6 @@ void State::initialize(Context *context)
mSamplerTextures[TextureType::External].resize(caps.maxCombinedTextureImageUnits);
}
mCompleteTextureBindings.reserve(caps.maxCombinedTextureImageUnits);
mCachedTexturesInitState = InitState::MayNeedInit;
mCachedImageTexturesInitState = InitState::MayNeedInit;
for (uint32_t textureIndex = 0; textureIndex < caps.maxCombinedTextureImageUnits;
++textureIndex)
{
......@@ -473,9 +469,9 @@ ANGLE_INLINE void State::updateActiveTextureState(const Context *context,
setTextureDirty(textureIndex);
}
if (texture->initState() == InitState::MayNeedInit)
if (mRobustResourceInit && texture->initState() == InitState::MayNeedInit)
{
mCachedTexturesInitState = InitState::MayNeedInit;
mDirtyObjects.set(DIRTY_OBJECT_TEXTURES_INIT);
}
}
......@@ -2579,6 +2575,39 @@ angle::Result State::syncProgram(const Context *context)
return mProgram->syncState(context);
}
angle::Result State::syncTexturesInit(const Context *context)
{
ASSERT(mRobustResourceInit);
if (!mProgram)
return angle::Result::Continue();
for (size_t textureUnitIndex : mProgram->getActiveSamplersMask())
{
Texture *texture = mActiveTexturesCache[textureUnitIndex];
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
return angle::Result::Continue();
}
angle::Result State::syncImagesInit(const Context *context)
{
ASSERT(mRobustResourceInit);
ASSERT(mProgram);
for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
{
Texture *texture = mImageUnits[imageUnitIndex].texture.get();
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
return angle::Result::Continue();
}
angle::Result State::syncDirtyObject(const Context *context, GLenum target)
{
DirtyObjects localSet;
......@@ -2677,9 +2706,9 @@ angle::Result State::onProgramExecutableChange(const Context *context, Program *
ANGLE_TRY(image->syncState(context));
}
if (image->initState() == InitState::MayNeedInit)
if (mRobustResourceInit && image->initState() == InitState::MayNeedInit)
{
mCachedImageTexturesInitState = InitState::MayNeedInit;
mDirtyObjects.set(DIRTY_OBJECT_IMAGES_INIT);
}
}
......@@ -2757,9 +2786,9 @@ void State::onImageStateChange(const Context *context, size_t unit)
mDirtyImages.set(unit);
}
if (image.texture->initState() == InitState::MayNeedInit)
if (mRobustResourceInit && image.texture->initState() == InitState::MayNeedInit)
{
mCachedImageTexturesInitState = InitState::MayNeedInit;
mDirtyObjects.set(DIRTY_OBJECT_IMAGES_INIT);
}
}
}
......@@ -2770,40 +2799,6 @@ void State::onUniformBufferStateChange(size_t uniformBufferIndex)
mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
}
angle::Result State::clearUnclearedActiveTextures(const Context *context)
{
ASSERT(mRobustResourceInit);
if (!mProgram)
return angle::Result::Continue();
if (mCachedTexturesInitState != InitState::Initialized)
{
for (size_t textureUnitIndex : mProgram->getActiveSamplersMask())
{
Texture *texture = mActiveTexturesCache[textureUnitIndex];
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
mCachedTexturesInitState = InitState::Initialized;
}
if (mCachedImageTexturesInitState != InitState::Initialized)
{
for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
{
Texture *texture = mImageUnits[imageUnitIndex].texture.get();
if (texture)
{
ANGLE_TRY(texture->ensureInitialized(context));
}
}
mCachedImageTexturesInitState = InitState::Initialized;
}
return angle::Result::Continue();
}
AttributesMask State::getAndResetDirtyCurrentValues() const
{
AttributesMask retVal = mDirtyCurrentValues;
......
......@@ -491,6 +491,8 @@ class State : angle::NonCopyable
DIRTY_OBJECT_IMAGES, // Top-level dirty bit. Also see mDirtyImages.
DIRTY_OBJECT_SAMPLERS, // Top-level dirty bit. Also see mDirtySamplers.
DIRTY_OBJECT_PROGRAM,
DIRTY_OBJECT_TEXTURES_INIT,
DIRTY_OBJECT_IMAGES_INIT,
DIRTY_OBJECT_UNKNOWN,
DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
};
......@@ -543,8 +545,6 @@ class State : angle::NonCopyable
void onUniformBufferStateChange(size_t uniformBufferIndex);
angle::Result clearUnclearedActiveTextures(const Context *context);
bool isCurrentTransformFeedback(const TransformFeedback *tf) const
{
return tf == mTransformFeedback.get();
......@@ -581,12 +581,15 @@ class State : angle::NonCopyable
angle::Result syncImages(const Context *context);
angle::Result syncSamplers(const Context *context);
angle::Result syncProgram(const Context *context);
angle::Result syncTexturesInit(const Context *context);
angle::Result syncImagesInit(const Context *context);
using DirtyObjectHandler = angle::Result (State::*)(const Context *context);
static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
&State::syncReadFramebuffer, &State::syncDrawFramebuffer, &State::syncDrawAttachments,
&State::syncVertexArray, &State::syncTextures, &State::syncImages,
&State::syncSamplers, &State::syncProgram};
&State::syncSamplers, &State::syncProgram, &State::syncTexturesInit,
&State::syncImagesInit};
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");
......@@ -596,6 +599,9 @@ class State : angle::NonCopyable
static_assert(DIRTY_OBJECT_IMAGES == 5, "check DIRTY_OBJECT_IMAGES index");
static_assert(DIRTY_OBJECT_SAMPLERS == 6, "check DIRTY_OBJECT_SAMPLERS index");
static_assert(DIRTY_OBJECT_PROGRAM == 7, "check DIRTY_OBJECT_PROGRAM index");
static_assert(DIRTY_OBJECT_TEXTURES_INIT == 8, "check DIRTY_OBJECT_TEXTURES_INIT index");
static_assert(DIRTY_OBJECT_IMAGES_INIT == 9, "check DIRTY_OBJECT_IMAGES_INIT index");
static_assert(DIRTY_OBJECT_MAX == 10, "check DIRTY_OBJECT_MAX");
// Dispatch table for buffer update functions.
static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
......@@ -671,9 +677,6 @@ class State : angle::NonCopyable
// Also stores a notification channel to the texture itself to handle texture change events.
ActiveTexturePointerArray mActiveTexturesCache;
std::vector<angle::ObserverBinding> mCompleteTextureBindings;
InitState mCachedTexturesInitState;
InitState mCachedImageTexturesInitState;
SamplerBindingVector mSamplers;
......
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