Skip Texture::syncState when no dirty bits.
We sometimes generate local dirty bits in TextureGL. To make sure the local
dirty bits don't get skipped we use a Subject/Observer pattern between the
TextureGL and gl::Texture. This allows us to skip syncState in the hot path.
Also inlines a couple of other texture functions. And fixes a stray header
in EGLBlobCacheTest.
Bug: angleproject:2763
Change-Id: Ie1d8a5865deaf2a563a358c31ae28bef6b2458b1
Reviewed-on: https://chromium-review.googlesource.com/1228374
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 12e805f..f2a7dec 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -1828,7 +1828,12 @@
angle::SubjectIndex index,
angle::SubjectMessage message)
{
- ASSERT(message == angle::SubjectMessage::STORAGE_CHANGED);
+ if (message != angle::SubjectMessage::STORAGE_CHANGED)
+ {
+ // This can be triggered by the GL back-end TextureGL class.
+ ASSERT(message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
+ return;
+ }
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
mDirtyBits.set(index);
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
index f92cb80..5050911 100644
--- a/src/libANGLE/FramebufferAttachment.cpp
+++ b/src/libANGLE/FramebufferAttachment.cpp
@@ -361,11 +361,6 @@
return getAttachmentImpl()->onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
}
-angle::Subject *FramebufferAttachmentObject::getSubject() const
-{
- return getAttachmentImpl();
-}
-
Error FramebufferAttachmentObject::initializeContents(const Context *context,
const ImageIndex &imageIndex)
{
diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h
index 2211df4..d2ef1f0 100644
--- a/src/libANGLE/FramebufferAttachment.h
+++ b/src/libANGLE/FramebufferAttachment.h
@@ -15,6 +15,7 @@
#include "libANGLE/Error.h"
#include "libANGLE/ImageIndex.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace egl
{
@@ -220,7 +221,7 @@
Error initializeContents(const Context *context, const ImageIndex &imageIndex);
void onStorageChange(const gl::Context *context) const;
- angle::Subject *getSubject() const;
+ angle::Subject *getSubject() const { return getAttachmentImpl(); }
protected:
virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index fcd6414..ba5c9a3 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -25,6 +25,7 @@
#include "libANGLE/queryconversions.h"
#include "libANGLE/queryutils.h"
#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/TextureImpl.h"
namespace gl
{
@@ -2756,7 +2757,10 @@
// TODO(jmadill): Use specific dirty bit for completeness change.
if (texture->isSamplerComplete(context, sampler))
{
- ANGLE_TRY(texture->syncState(context));
+ if (texture->hasAnyDirtyBit())
+ {
+ ANGLE_TRY(texture->syncState(context));
+ }
mActiveTexturesCache[textureUnitIndex] = texture;
}
else
@@ -2765,7 +2769,7 @@
}
// Bind the texture unconditionally, to recieve completeness change notifications.
- mCompleteTextureBindings[textureUnitIndex].bind(texture->getSubject());
+ mCompleteTextureBindings[textureUnitIndex].bind(texture->getImplementation());
newActiveTextures.set(textureUnitIndex);
if (texture->initState() == InitState::MayNeedInit)
@@ -2792,7 +2796,10 @@
{
continue;
}
- ANGLE_TRY(texture->syncState(context));
+ if (texture->hasAnyDirtyBit())
+ {
+ ANGLE_TRY(texture->syncState(context));
+ }
if (texture->initState() == InitState::MayNeedInit)
{
mCachedImageTexturesInitState = InitState::MayNeedInit;
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index ba52eb6..9b450b2 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -584,10 +584,15 @@
: RefCountObject(id),
mState(type),
mTexture(factory->createTexture(mState)),
+ mImplObserver(this, 0),
mLabel(),
mBoundSurface(nullptr),
mBoundStream(nullptr)
{
+ mImplObserver.bind(mTexture);
+
+ // Initially assume the implementation is dirty.
+ mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
}
Error Texture::onDestroy(const Context *context)
@@ -1255,7 +1260,11 @@
{
return NoError();
}
- ANGLE_TRY(syncState(context));
+
+ if (hasAnyDirtyBit())
+ {
+ ANGLE_TRY(syncState(context));
+ }
// Clear the base image(s) immediately if needed
if (context->isRobustResourceInitEnabled())
@@ -1515,6 +1524,7 @@
Error Texture::syncState(const Context *context)
{
+ ASSERT(hasAnyDirtyBit());
ANGLE_TRY(mTexture->syncState(context, mDirtyBits));
mDirtyBits.reset();
return NoError();
@@ -1607,11 +1617,6 @@
return mState.getImageDesc(imageIndex).initState;
}
-InitState Texture::initState() const
-{
- return mState.mInitState;
-}
-
void Texture::setInitState(const ImageIndex &imageIndex, InitState initState)
{
// As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
@@ -1673,4 +1678,13 @@
return NoError();
}
+void Texture::onSubjectStateChange(const gl::Context *context,
+ angle::SubjectIndex index,
+ angle::SubjectMessage message)
+{
+ if (message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS)
+ {
+ mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
+ }
+}
} // namespace gl
diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h
index 420ca17..42c108b 100644
--- a/src/libANGLE/Texture.h
+++ b/src/libANGLE/Texture.h
@@ -21,6 +21,7 @@
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Image.h"
+#include "libANGLE/Observer.h"
#include "libANGLE/Stream.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
@@ -187,7 +188,10 @@
bool operator==(const TextureState &a, const TextureState &b);
bool operator!=(const TextureState &a, const TextureState &b);
-class Texture final : public RefCountObject, public egl::ImageSibling, public LabeledObject
+class Texture final : public RefCountObject,
+ public egl::ImageSibling,
+ public LabeledObject,
+ public angle::ObserverInterface
{
public:
Texture(rx::GLImplFactory *factory, GLuint id, TextureType type);
@@ -397,7 +401,7 @@
// Needed for robust resource init.
Error ensureInitialized(const Context *context);
InitState initState(const ImageIndex &imageIndex) const override;
- InitState initState() const;
+ InitState initState() const { return mState.mInitState; }
void setInitState(const ImageIndex &imageIndex, InitState initState) override;
enum DirtyBitType
@@ -427,6 +431,7 @@
// Misc
DIRTY_BIT_LABEL,
DIRTY_BIT_USAGE,
+ DIRTY_BIT_IMPLEMENTATION,
DIRTY_BIT_COUNT,
};
@@ -435,6 +440,11 @@
Error syncState(const Context *context);
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+ // ObserverInterface implementation.
+ void onSubjectStateChange(const gl::Context *context,
+ angle::SubjectIndex index,
+ angle::SubjectMessage message) override;
+
private:
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
@@ -464,6 +474,7 @@
TextureState mState;
DirtyBits mDirtyBits;
rx::TextureImpl *mTexture;
+ angle::ObserverBinding mImplObserver;
std::string mLabel;
diff --git a/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h b/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
index 334e2f2..bd82410 100644
--- a/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
+++ b/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
@@ -11,11 +11,12 @@
#ifndef LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
#define LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
-#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/ImageIndex.h"
#include "libANGLE/Observer.h"
namespace rx
{
+class FramebufferAttachmentRenderTarget;
class FramebufferAttachmentObjectImpl : public angle::Subject
{
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index b95b6d8..271f441 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -235,7 +235,8 @@
UNREACHABLE();
}
- setLevelInfo(target, level, 1, GetLevelInfo(internalFormat, texImageFormat.internalFormat));
+ setLevelInfo(context, target, level, 1,
+ GetLevelInfo(internalFormat, texImageFormat.internalFormat));
}
void TextureGL::reserveTexImageToBeFilled(const gl::Context *context,
@@ -508,7 +509,7 @@
LevelInfoGL levelInfo = GetLevelInfo(internalFormat, compressedTexImageFormat.internalFormat);
ASSERT(!levelInfo.lumaWorkaround.enabled);
- setLevelInfo(target, level, 1, levelInfo);
+ setLevelInfo(context, target, level, 1, levelInfo);
return gl::NoError();
}
@@ -660,7 +661,7 @@
UNREACHABLE();
}
- setLevelInfo(target, level, 1, levelInfo);
+ setLevelInfo(context, target, level, 1, levelInfo);
}
return gl::NoError();
@@ -1007,7 +1008,8 @@
UNREACHABLE();
}
- setLevelInfo(type, 0, levels, GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
+ setLevelInfo(context, type, 0, levels,
+ GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
return gl::NoError();
}
@@ -1046,7 +1048,8 @@
UNREACHABLE();
}
- setLevelInfo(type, 0, 1, GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
+ setLevelInfo(context, type, 0, 1,
+ GetLevelInfo(internalFormat, texStorageFormat.internalFormat));
return gl::NoError();
}
@@ -1071,7 +1074,8 @@
const GLuint effectiveBaseLevel = mState.getEffectiveBaseLevel();
const GLuint maxLevel = mState.getMipmapMaxLevel();
- setLevelInfo(getType(), effectiveBaseLevel, maxLevel - effectiveBaseLevel, getBaseLevelInfo());
+ setLevelInfo(context, getType(), effectiveBaseLevel, maxLevel - effectiveBaseLevel,
+ getBaseLevelInfo());
return gl::NoError();
}
@@ -1085,7 +1089,7 @@
// Make sure this texture is bound
stateManager->bindTexture(getType(), mTextureID);
- setLevelInfo(getType(), 0, 1, LevelInfoGL());
+ setLevelInfo(context, getType(), 0, 1, LevelInfoGL());
return gl::NoError();
}
@@ -1119,7 +1123,7 @@
GLenum imageNativeInternalFormat = GL_NONE;
ANGLE_TRY(imageGL->setTexture2D(context, type, this, &imageNativeInternalFormat));
- setLevelInfo(type, 0, 1,
+ setLevelInfo(context, type, 0, 1,
GetLevelInfo(image->getFormat().info->internalFormat, imageNativeInternalFormat));
return gl::NoError();
@@ -1247,6 +1251,11 @@
case gl::Texture::DIRTY_BIT_LABEL:
break;
+ case gl::Texture::DIRTY_BIT_IMPLEMENTATION:
+ // This special dirty bit is used to signal the front-end that the implementation
+ // has local dirty bits. The real dirty bits are in mLocalDirty bits.
+ break;
+
default:
UNREACHABLE();
}
@@ -1271,6 +1280,9 @@
mAppliedBaseLevel = baseLevel;
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_BASE_LEVEL);
+ // Signal to the GL layer that the Impl has dirty bits.
+ onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
+
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_BASE_LEVEL, baseLevel);
}
@@ -1287,6 +1299,9 @@
mAppliedSampler.setMinFilter(filter);
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MIN_FILTER);
+ // Signal to the GL layer that the Impl has dirty bits.
+ onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
+
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MIN_FILTER, filter);
}
@@ -1301,6 +1316,9 @@
mAppliedSampler.setMagFilter(filter);
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAG_FILTER);
+ // Signal to the GL layer that the Impl has dirty bits.
+ onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
+
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_MAG_FILTER, filter);
}
@@ -1322,6 +1340,9 @@
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE);
mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
+ // Signal to the GL layer that the Impl has dirty bits.
+ onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
+
stateManager->bindTexture(getType(), mTextureID);
functions->texParameteriv(ToGLenum(getType()), GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
@@ -1446,7 +1467,8 @@
functions->texParameteri(ToGLenum(getType()), name, resultSwizzle);
}
-void TextureGL::setLevelInfo(gl::TextureTarget target,
+void TextureGL::setLevelInfo(const gl::Context *context,
+ gl::TextureTarget target,
size_t level,
size_t levelCount,
const LevelInfoGL &levelInfo)
@@ -1470,10 +1492,12 @@
if (updateWorkarounds)
{
mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
+ onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
}
-void TextureGL::setLevelInfo(gl::TextureType type,
+void TextureGL::setLevelInfo(const gl::Context *context,
+ gl::TextureType type,
size_t level,
size_t levelCount,
const LevelInfoGL &levelInfo)
@@ -1482,12 +1506,12 @@
{
for (gl::TextureTarget target : gl::AllCubeFaceTextureTargets())
{
- setLevelInfo(target, level, levelCount, levelInfo);
+ setLevelInfo(context, target, level, levelCount, levelInfo);
}
}
else
{
- setLevelInfo(NonCubeTextureTypeToTarget(type), level, levelCount, levelInfo);
+ setLevelInfo(context, NonCubeTextureTypeToTarget(type), level, levelCount, levelInfo);
}
}
diff --git a/src/libANGLE/renderer/gl/TextureGL.h b/src/libANGLE/renderer/gl/TextureGL.h
index 52fc880..3260e9a 100644
--- a/src/libANGLE/renderer/gl/TextureGL.h
+++ b/src/libANGLE/renderer/gl/TextureGL.h
@@ -223,11 +223,13 @@
GLenum value,
GLenum *outValue);
- void setLevelInfo(gl::TextureTarget target,
+ void setLevelInfo(const gl::Context *context,
+ gl::TextureTarget target,
size_t level,
size_t levelCount,
const LevelInfoGL &levelInfo);
- void setLevelInfo(gl::TextureType type,
+ void setLevelInfo(const gl::Context *context,
+ gl::TextureType type,
size_t level,
size_t levelCount,
const LevelInfoGL &levelInfo);
diff --git a/src/tests/egl_tests/EGLBlobCacheTest.cpp b/src/tests/egl_tests/EGLBlobCacheTest.cpp
index 76a7002..987892f 100644
--- a/src/tests/egl_tests/EGLBlobCacheTest.cpp
+++ b/src/tests/egl_tests/EGLBlobCacheTest.cpp
@@ -12,8 +12,6 @@
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
-#include "libANGLE/validationEGL.h"
-
using namespace angle;
constexpr char kEGLExtName[] = "EGL_ANDROID_blob_cache";