Commit 9aded17c by Geoff Lang

Invalidate completeness caches when enabling extensions.

Enabling extensions can cause framebuffers and textures to go from incomplete to complete. No functional changes from the API surface. BUG=angleproject:1523 BUG=angleproject:1958 Change-Id: Iff686e1c292f6cf4921d6fffd7eb98bedaba828b Reviewed-on: https://chromium-review.googlesource.com/468410 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 60e17eab
......@@ -2511,6 +2511,16 @@ void Context::requestExtension(const char *name)
// Re-create the compiler with the requested extensions enabled.
SafeDelete(mCompiler);
mCompiler = new Compiler(mImplementation.get(), mState);
// Invalidate all cached completenesses for textures and framebuffer. Some extensions make new
// formats renderable or sampleable.
mState.mTextures->invalidateTextureComplenessCache();
for (auto &zeroTexture : mZeroTextures)
{
zeroTexture.second->invalidateCompletenessCache();
}
mState.mFramebuffers->invalidateFramebufferComplenessCache();
}
size_t Context::getRequestableExtensionStringCount() const
......
......@@ -61,7 +61,7 @@ TextureManager *AllocateOrGetSharedTextureManager(const ContextState *shareConte
} // anonymous namespace
ContextState::ContextState(uintptr_t contextIn,
ContextState::ContextState(ContextID contextIn,
const ContextState *shareContextState,
TextureManager *shareTextures,
const Version &clientVersion,
......@@ -117,7 +117,7 @@ ValidationContext::ValidationContext(const ValidationContext *shareContext,
const Extensions &extensions,
const Limitations &limitations,
bool skipValidation)
: mState(reinterpret_cast<uintptr_t>(this),
: mState(reinterpret_cast<ContextID>(this),
shareContext ? &shareContext->mState : nullptr,
shareTextures,
clientVersion,
......
......@@ -30,10 +30,12 @@ static constexpr Version ES_2_0 = Version(2, 0);
static constexpr Version ES_3_0 = Version(3, 0);
static constexpr Version ES_3_1 = Version(3, 1);
using ContextID = uintptr_t;
class ContextState final : public angle::NonCopyable
{
public:
ContextState(uintptr_t context,
ContextState(ContextID context,
const ContextState *shareContextState,
TextureManager *shareTextures,
const Version &clientVersion,
......@@ -44,7 +46,7 @@ class ContextState final : public angle::NonCopyable
const Limitations &limitations);
~ContextState();
uintptr_t getContext() const { return mContext; }
ContextID getContextID() const { return mContext; }
GLint getClientMajorVersion() const { return mClientVersion.major; }
GLint getClientMinorVersion() const { return mClientVersion.minor; }
const Version &getClientVersion() const { return mClientVersion; }
......@@ -65,7 +67,7 @@ class ContextState final : public angle::NonCopyable
friend class ValidationContext;
Version mClientVersion;
uintptr_t mContext;
ContextID mContext;
State *mState;
const Caps &mCaps;
const TextureCapsMap &mTextureCaps;
......
......@@ -568,6 +568,14 @@ bool Framebuffer::usingExtendedDrawBuffers() const
return false;
}
void Framebuffer::invalidateCompletenessCache()
{
if (mId != 0)
{
mCachedStatus.reset();
}
}
GLenum Framebuffer::checkStatus(const Context *context)
{
// The default framebuffer is always complete except when it is surfaceless in which
......
......@@ -188,6 +188,8 @@ class Framebuffer final : public LabeledObject, public angle::SignalReceiver
void setDefaultSamples(GLint defaultSamples);
void setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations);
void invalidateCompletenessCache();
GLenum checkStatus(const Context *context);
// TODO(jmadill): Remove this kludge.
......
......@@ -304,6 +304,17 @@ bool TextureManager::isTextureGenerated(GLuint texture) const
return texture == 0 || mObjectMap.find(texture) != mObjectMap.end();
}
void TextureManager::invalidateTextureComplenessCache()
{
for (auto &texture : mObjectMap)
{
if (texture.second)
{
texture.second->invalidateCompletenessCache();
}
}
}
// RenderbufferManager Implementation.
// static
......@@ -497,4 +508,15 @@ bool FramebufferManager::isFramebufferGenerated(GLuint framebuffer)
return mObjectMap.find(framebuffer) != mObjectMap.end();
}
void FramebufferManager::invalidateFramebufferComplenessCache()
{
for (auto &framebuffer : mObjectMap)
{
if (framebuffer.second)
{
framebuffer.second->invalidateCompletenessCache();
}
}
}
} // namespace gl
......@@ -150,6 +150,8 @@ class TextureManager : public TypedResourceManager<Texture, HandleAllocator, Tex
Texture *getTexture(GLuint handle) const;
bool isTextureGenerated(GLuint texture) const;
void invalidateTextureComplenessCache();
Texture *checkTextureAllocation(rx::GLImplFactory *factory, GLuint handle, GLenum target)
{
return checkObjectAllocation(factory, handle, target);
......@@ -238,6 +240,8 @@ class FramebufferManager
void setDefaultFramebuffer(Framebuffer *framebuffer);
bool isFramebufferGenerated(GLuint framebuffer);
void invalidateFramebufferComplenessCache();
Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
const Caps &caps,
GLuint handle)
......
......@@ -156,8 +156,8 @@ bool TextureState::setBaseLevel(GLuint baseLevel)
{
if (mBaseLevel != baseLevel)
{
mBaseLevel = baseLevel;
mCompletenessCache.cacheValid = false;
mBaseLevel = baseLevel;
invalidateCompletenessCache();
return true;
}
return false;
......@@ -167,8 +167,8 @@ void TextureState::setMaxLevel(GLuint maxLevel)
{
if (mMaxLevel != maxLevel)
{
mMaxLevel = maxLevel;
mCompletenessCache.cacheValid = false;
mMaxLevel = maxLevel;
invalidateCompletenessCache();
}
}
......@@ -200,21 +200,28 @@ bool TextureState::isCubeComplete() const
bool TextureState::isSamplerComplete(const SamplerState &samplerState,
const ContextState &data) const
{
const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
const TextureCaps &textureCaps = data.getTextureCap(baseImageDesc.format.asSized());
if (!mCompletenessCache.cacheValid || mCompletenessCache.samplerState != samplerState ||
mCompletenessCache.filterable != textureCaps.filterable ||
mCompletenessCache.clientVersion != data.getClientMajorVersion() ||
mCompletenessCache.supportsNPOT != data.getExtensions().textureNPOT)
auto cacheIter = mCompletenessCache.find(data.getContextID());
if (cacheIter == mCompletenessCache.end())
{
mCompletenessCache.cacheValid = true;
mCompletenessCache.samplerState = samplerState;
mCompletenessCache.filterable = textureCaps.filterable;
mCompletenessCache.clientVersion = data.getClientMajorVersion();
mCompletenessCache.supportsNPOT = data.getExtensions().textureNPOT;
mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data);
// Add a new cache entry
cacheIter = mCompletenessCache
.insert(std::make_pair(data.getContextID(), SamplerCompletenessCache()))
.first;
}
return mCompletenessCache.samplerComplete;
auto cacheEntry = cacheIter->second;
if (!cacheEntry.cacheValid || cacheEntry.samplerState != samplerState)
{
cacheEntry.cacheValid = true;
cacheEntry.samplerComplete = computeSamplerCompleteness(samplerState, data);
}
return cacheEntry.samplerComplete;
}
void TextureState::invalidateCompletenessCache()
{
mCompletenessCache.clear();
}
bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
......@@ -442,8 +449,8 @@ void TextureState::setImageDesc(GLenum target, size_t level, const ImageDesc &de
{
size_t descIndex = GetImageDescIndex(target, level);
ASSERT(descIndex < mImageDescs.size());
mImageDescs[descIndex] = desc;
mCompletenessCache.cacheValid = false;
mImageDescs[descIndex] = desc;
invalidateCompletenessCache();
}
void TextureState::setImageDescChain(GLuint baseLevel,
......@@ -496,15 +503,12 @@ void TextureState::clearImageDescs()
{
mImageDescs[descIndex] = ImageDesc();
}
mCompletenessCache.cacheValid = false;
invalidateCompletenessCache();
}
TextureState::SamplerCompletenessCache::SamplerCompletenessCache()
: cacheValid(false),
samplerState(),
filterable(false),
clientVersion(0),
supportsNPOT(false),
samplerComplete(false)
{
}
......@@ -845,6 +849,12 @@ egl::Stream *Texture::getBoundStream() const
return mBoundStream;
}
void Texture::invalidateCompletenessCache()
{
mState.invalidateCompletenessCache();
mDirtyChannel.signal();
}
Error Texture::setImage(const Context *context,
const PixelUnpackState &unpackState,
GLenum target,
......
......@@ -100,6 +100,8 @@ struct TextureState final : public angle::NonCopyable
bool isCubeComplete() const;
bool isSamplerComplete(const SamplerState &samplerState, const ContextState &data) const;
void invalidateCompletenessCache();
const ImageDesc &getImageDesc(GLenum target, size_t level) const;
GLenum getTarget() const { return mTarget; }
......@@ -162,14 +164,12 @@ struct TextureState final : public angle::NonCopyable
// All values that affect sampler completeness that are not stored within
// the texture itself
SamplerState samplerState;
bool filterable;
GLint clientVersion;
bool supportsNPOT;
// Result of the sampler completeness with the above parameters
bool samplerComplete;
};
mutable SamplerCompletenessCache mCompletenessCache;
mutable std::unordered_map<ContextID, SamplerCompletenessCache> mCompletenessCache;
};
bool operator==(const TextureState &a, const TextureState &b);
......@@ -354,6 +354,8 @@ class Texture final : public egl::ImageSibling,
egl::Surface *getBoundSurface() const;
egl::Stream *getBoundStream() const;
void invalidateCompletenessCache();
rx::TextureImpl *getImplementation() const { return mTexture; }
// FramebufferAttachmentObject implementation
......
......@@ -262,6 +262,8 @@ typedef std::bitset<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> UniformB
// Client code should treat it as a std::map.
template <class ResourceT>
using ResourceMap = std::unordered_map<GLuint, ResourceT *>;
using ContextID = uintptr_t;
}
namespace rx
......
......@@ -734,13 +734,13 @@ gl::Error StateManagerGL::onMakeCurrent(const gl::ContextState &data)
const gl::State &state = data.getState();
// If the context has changed, pause the previous context's queries
if (data.getContext() != mPrevDrawContext)
if (data.getContextID() != mPrevDrawContext)
{
pauseAllQueries();
}
mCurrentQueries.clear();
mPrevDrawTransformFeedback = nullptr;
mPrevDrawContext = data.getContext();
mPrevDrawContext = data.getContextID();
// Set the current query state
for (GLenum queryType : QueryTypes)
......
......@@ -202,7 +202,7 @@ class StateManagerGL final : angle::NonCopyable
TransformFeedbackGL *mPrevDrawTransformFeedback;
std::set<QueryGL *> mCurrentQueries;
uintptr_t mPrevDrawContext;
gl::ContextID mPrevDrawContext;
GLint mUnpackAlignment;
GLint mUnpackRowLength;
......
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