Commit ea3f501e by Jamie Madill Committed by Commit Bot

Feedback Loop Redesign 3/3: Remove feedback loop tracking.

We now we detect feedback loops by tracking the Framebuffers that the Texture is bound to. We still have the old tracking method that counts sampler and image bindings in the code as well. This CL removes the old front-end tracking for feedback loops. It's no longer used by any back-ends. This removal should reduce CPU overhead around Texture and Program binding changes. Reverts the image binding tracking to the simpler scheme that tracks if a Texture has ever been bound as an Image. This should practically have little or no perf effect and we can reinstate some simpler tracking in the future if required. Bug: angleproject:4500 Bug: angleproject:4959 Change-Id: Idc625d6e4c519919f97a4dc72dd9c35d262706fb Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2363210 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTobin Ehlis <tobine@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com>
parent ba1e049f
......@@ -1080,8 +1080,7 @@ void Context::bindTexture(TextureType target, TextureID handle)
void Context::bindReadFramebuffer(FramebufferID framebufferHandle)
{
Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
mImplementation.get(), mState.mCaps, framebufferHandle, mState.getContextID(),
getShareGroup());
mImplementation.get(), mState.mCaps, framebufferHandle, getShareGroup());
mState.setReadFramebufferBinding(framebuffer);
mReadFramebufferObserverBinding.bind(framebuffer);
}
......@@ -1089,8 +1088,7 @@ void Context::bindReadFramebuffer(FramebufferID framebufferHandle)
void Context::bindDrawFramebuffer(FramebufferID framebufferHandle)
{
Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
mImplementation.get(), mState.mCaps, framebufferHandle, mState.getContextID(),
getShareGroup());
mImplementation.get(), mState.mCaps, framebufferHandle, getShareGroup());
mState.setDrawFramebufferBinding(framebuffer);
mDrawFramebufferObserverBinding.bind(framebuffer);
mStateCache.onDrawFramebufferChange(this);
......
......@@ -265,10 +265,9 @@ angle::Result InitAttachment(const Context *context, FramebufferAttachment *atta
} // anonymous namespace
// This constructor is only used for default framebuffers.
FramebufferState::FramebufferState(ContextID owningContextID, rx::Serial serial)
FramebufferState::FramebufferState(rx::Serial serial)
: mId(Framebuffer::kDefaultDrawFramebufferHandle),
mFramebufferSerial(serial),
mOwningContextID(owningContextID),
mLabel(),
mColorAttachments(1),
mDrawBufferStates(1, GL_BACK),
......@@ -280,22 +279,15 @@ FramebufferState::FramebufferState(ContextID owningContextID, rx::Serial serial)
mDefaultFixedSampleLocations(GL_FALSE),
mDefaultLayers(0),
mWebGLDepthStencilConsistent(true),
mDepthBufferFeedbackLoop(false),
mStencilBufferFeedbackLoop(false),
mHasRenderingFeedbackLoop(false),
mDefaultFramebufferReadAttachmentInitialized(false)
{
ASSERT(mDrawBufferStates.size() > 0);
mEnabledDrawBuffers.set(0);
}
FramebufferState::FramebufferState(const Caps &caps,
FramebufferID id,
ContextID owningContextID,
rx::Serial serial)
FramebufferState::FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial)
: mId(id),
mFramebufferSerial(serial),
mOwningContextID(owningContextID),
mLabel(),
mColorAttachments(caps.maxColorAttachments),
mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
......@@ -307,9 +299,6 @@ FramebufferState::FramebufferState(const Caps &caps,
mDefaultFixedSampleLocations(GL_FALSE),
mDefaultLayers(0),
mWebGLDepthStencilConsistent(true),
mDepthBufferFeedbackLoop(false),
mStencilBufferFeedbackLoop(false),
mHasRenderingFeedbackLoop(false),
mDefaultFramebufferReadAttachmentInitialized(false)
{
ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle);
......@@ -661,61 +650,13 @@ bool FramebufferState::isDefault() const
return mId == Framebuffer::kDefaultDrawFramebufferHandle;
}
bool FramebufferState::updateAttachmentFeedbackLoopAndReturnIfChanged(size_t dirtyBit)
{
bool previous;
bool loop;
switch (dirtyBit)
{
case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
previous = mDepthBufferFeedbackLoop;
loop = mDepthAttachment.isBoundAsSamplerOrImage(mOwningContextID);
mDepthBufferFeedbackLoop = loop;
break;
case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
previous = mStencilBufferFeedbackLoop;
loop = mStencilAttachment.isBoundAsSamplerOrImage(mOwningContextID);
mStencilBufferFeedbackLoop = loop;
break;
default:
{
ASSERT(dirtyBit <= Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
previous = mDrawBufferFeedbackLoops.test(dirtyBit);
loop = mColorAttachments[dirtyBit].isBoundAsSamplerOrImage(mOwningContextID);
mDrawBufferFeedbackLoops[dirtyBit] = loop;
break;
}
}
updateHasRenderingFeedbackLoop();
return previous != loop;
}
void FramebufferState::updateHasRenderingFeedbackLoop()
{
// We don't handle tricky cases where the default FBO is bound as a sampler.
// We also don't handle tricky cases with EGLImages and mipmap selection.
// TODO(http://anglebug.com/4500): Tricky rendering feedback loop cases.
if (isDefault())
{
return;
}
mHasRenderingFeedbackLoop =
mDrawBufferFeedbackLoops.any() || mDepthBufferFeedbackLoop || mStencilBufferFeedbackLoop;
}
const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0};
Framebuffer::Framebuffer(const Caps &caps,
rx::GLImplFactory *factory,
FramebufferID id,
ContextID owningContextID,
egl::ShareGroup *shareGroup)
: mState(caps, id, owningContextID, shareGroup->generateFramebufferSerial()),
: mState(caps, id, shareGroup->generateFramebufferSerial()),
mImpl(factory->createFramebuffer(mState)),
mCachedStatus(),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
......@@ -733,7 +674,7 @@ Framebuffer::Framebuffer(const Caps &caps,
}
Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface)
: mState(context->id(), context->getShareGroup()->generateFramebufferSerial()),
: mState(context->getShareGroup()->generateFramebufferSerial()),
mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
......@@ -775,7 +716,7 @@ Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Sur
Framebuffer::Framebuffer(const Context *context,
rx::GLImplFactory *factory,
egl::Surface *readSurface)
: mState(context->id(), context->getShareGroup()->generateFramebufferSerial()),
: mState(context->getShareGroup()->generateFramebufferSerial()),
mImpl(factory->createFramebuffer(mState)),
mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
......@@ -1876,7 +1817,6 @@ void Framebuffer::updateAttachment(const Context *context,
mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
onDirtyBinding->bind(resource);
mState.updateAttachmentFeedbackLoopAndReturnIfChanged(dirtyBit);
invalidateCompletenessCache();
}
......@@ -1911,16 +1851,7 @@ void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::Subject
return;
}
// Triggered by changes to Texture feedback loops.
if (message == angle::SubjectMessage::BindingChanged)
{
if (mState.updateAttachmentFeedbackLoopAndReturnIfChanged(index))
{
mDirtyBits.set(index);
onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
}
return;
}
ASSERT(message != angle::SubjectMessage::BindingChanged);
// This can be triggered by external changes to the default framebuffer.
if (message == angle::SubjectMessage::SurfaceChanged)
......
......@@ -53,11 +53,8 @@ class TextureCapsMap;
class FramebufferState final : angle::NonCopyable
{
public:
explicit FramebufferState(ContextID owningContextID, rx::Serial serial);
FramebufferState(const Caps &caps,
FramebufferID id,
ContextID owningContextID,
rx::Serial serial);
explicit FramebufferState(rx::Serial serial);
FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial);
~FramebufferState();
const std::string &getLabel() const;
......@@ -119,11 +116,6 @@ class FramebufferState final : angle::NonCopyable
bool isDefault() const;
bool hasDepthStencilFeedbackLoop() const
{
return mDepthBufferFeedbackLoop || mStencilBufferFeedbackLoop;
}
const gl::Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
rx::Serial getFramebufferSerial() const { return mFramebufferSerial; }
......@@ -133,19 +125,12 @@ class FramebufferState final : angle::NonCopyable
const FramebufferAttachment *getWebGLDepthAttachment() const;
const FramebufferAttachment *getWebGLStencilAttachment() const;
// Returns true if there was a change in this attachments feedback-loop-ness.
bool updateAttachmentFeedbackLoopAndReturnIfChanged(size_t dirtyBit);
void updateHasRenderingFeedbackLoop();
friend class Framebuffer;
// The Framebuffer ID is unique to a Context.
// The Framebuffer Serial is unique to a Share Group.
FramebufferID mId;
rx::Serial mFramebufferSerial;
// TODO(jmadill): Remove the owning context ID. http://anglebug.com/4500
ContextID mOwningContextID;
std::string mLabel;
std::vector<FramebufferAttachment> mColorAttachments;
......@@ -170,13 +155,6 @@ class FramebufferState final : angle::NonCopyable
FramebufferAttachment mWebGLStencilAttachment;
bool mWebGLDepthStencilConsistent;
// Tracks rendering feedback loops.
// TODO(jmadill): Remove. http://anglebug.com/4500
DrawBufferMask mDrawBufferFeedbackLoops;
bool mDepthBufferFeedbackLoop;
bool mStencilBufferFeedbackLoop;
bool mHasRenderingFeedbackLoop;
// Tracks if we need to initialize the resources for each attachment.
angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
......@@ -195,7 +173,6 @@ class Framebuffer final : public angle::ObserverInterface,
Framebuffer(const Caps &caps,
rx::GLImplFactory *factory,
FramebufferID id,
ContextID owningContextID,
egl::ShareGroup *shareGroup);
// Constructor to build default framebuffers for a surface and context pair
Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface);
......@@ -410,9 +387,6 @@ class Framebuffer final : public angle::ObserverInterface,
// Observer implementation
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
// TODO(jmadill): Remove. http://anglebug.com/4500
bool hasRenderingFeedbackLoop() const { return mState.mHasRenderingFeedbackLoop; }
bool formsRenderingFeedbackLoopWith(const Context *context) const;
bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
GLint copyTextureLevel,
......
......@@ -283,18 +283,6 @@ void FramebufferAttachment::setInitState(InitState initState) const
mResource->setInitState(mTarget.textureIndex(), initState);
}
bool FramebufferAttachment::isBoundAsSamplerOrImage(ContextID contextID) const
{
if (mType != GL_TEXTURE)
{
return false;
}
const gl::TextureState &textureState = getTexture()->getTextureState();
return textureState.isBoundAsImageTexture(contextID) ||
textureState.isBoundAsSamplerTexture(contextID);
}
////// FramebufferAttachmentObject Implementation //////
FramebufferAttachmentObject::FramebufferAttachmentObject() {}
......
......@@ -94,8 +94,6 @@ class FramebufferAttachment final
GLenum getComponentType() const;
GLenum getColorEncoding() const;
bool isBoundAsSamplerOrImage(ContextID contextID) const;
bool isTextureWithId(TextureID textureId) const
{
return mType == GL_TEXTURE && id() == textureId.value;
......
......@@ -351,12 +351,11 @@ Sync *SyncManager::getSync(GLuint handle) const
Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
FramebufferID handle,
const Caps &caps,
ContextID owningContextID,
egl::ShareGroup *shareGroup)
{
// Make sure the caller isn't using a reserved handle.
ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
return new Framebuffer(caps, factory, handle, owningContextID, shareGroup);
return new Framebuffer(caps, factory, handle, shareGroup);
}
// static
......
......@@ -281,17 +281,14 @@ class FramebufferManager
Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
const Caps &caps,
FramebufferID handle,
ContextID owningContextID,
egl::ShareGroup *shareGroup)
{
return checkObjectAllocation<const Caps &>(factory, handle, caps, owningContextID,
shareGroup);
return checkObjectAllocation<const Caps &>(factory, handle, caps, shareGroup);
}
static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
FramebufferID handle,
const Caps &caps,
ContextID owningContextID,
egl::ShareGroup *shareGroup);
static void DeleteObject(const Context *context, Framebuffer *framebuffer);
......
......@@ -245,11 +245,11 @@ ActiveTexturesCache::~ActiveTexturesCache()
ASSERT(empty());
}
void ActiveTexturesCache::clear(ContextID contextID)
void ActiveTexturesCache::clear()
{
for (size_t textureIndex = 0; textureIndex < mTextures.size(); ++textureIndex)
{
reset(contextID, textureIndex);
reset(textureIndex);
}
}
......@@ -266,27 +266,17 @@ bool ActiveTexturesCache::empty() const
return true;
}
ANGLE_INLINE void ActiveTexturesCache::reset(ContextID contextID, size_t textureIndex)
ANGLE_INLINE void ActiveTexturesCache::reset(size_t textureIndex)
{
if (mTextures[textureIndex])
{
mTextures[textureIndex]->onUnbindAsSamplerTexture(contextID);
mTextures[textureIndex] = nullptr;
}
}
ANGLE_INLINE void ActiveTexturesCache::set(ContextID contextID,
size_t textureIndex,
Texture *texture)
ANGLE_INLINE void ActiveTexturesCache::set(size_t textureIndex, Texture *texture)
{
// We don't call reset() here to avoid setting nullptr before rebind.
if (mTextures[textureIndex])
{
mTextures[textureIndex]->onUnbindAsSamplerTexture(contextID);
}
ASSERT(texture);
texture->onBindAsSamplerTexture(contextID);
mTextures[textureIndex] = texture;
}
......@@ -514,7 +504,7 @@ void State::initialize(Context *context)
void State::reset(const Context *context)
{
mActiveTexturesCache.clear(mID);
mActiveTexturesCache.clear();
for (auto &bindingVec : mSamplerTextures)
{
......@@ -589,7 +579,7 @@ ANGLE_INLINE void State::unsetActiveTextures(ActiveTextureMask textureMask)
// Unset any relevant bound textures.
for (size_t textureIndex : textureMask)
{
mActiveTexturesCache.reset(mID, textureIndex);
mActiveTexturesCache.reset(textureIndex);
mCompleteTextureBindings[textureIndex].reset();
}
}
......@@ -601,11 +591,11 @@ ANGLE_INLINE void State::updateActiveTextureState(const Context *context,
{
if (!texture || !texture->isSamplerComplete(context, sampler))
{
mActiveTexturesCache.reset(mID, textureIndex);
mActiveTexturesCache.reset(textureIndex);
}
else
{
mActiveTexturesCache.set(mID, textureIndex, texture);
mActiveTexturesCache.set(textureIndex, texture);
if (texture->hasAnyDirtyBit())
{
......@@ -644,7 +634,7 @@ ANGLE_INLINE void State::updateActiveTexture(const Context *context,
if (!texture)
{
mActiveTexturesCache.reset(mID, textureIndex);
mActiveTexturesCache.reset(textureIndex);
mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
return;
}
......@@ -3377,13 +3367,9 @@ void State::setImageUnit(const Context *context,
{
ImageUnit &imageUnit = mImageUnits[unit];
if (imageUnit.texture.get())
{
imageUnit.texture->onUnbindAsImageTexture(mID);
}
if (texture)
{
texture->onBindAsImageTexture(mID);
texture->onBindAsImageTexture();
}
imageUnit.texture.set(context, texture);
imageUnit.level = level;
......
......@@ -78,9 +78,9 @@ class ActiveTexturesCache final : angle::NonCopyable
Texture *operator[](size_t textureIndex) const { return mTextures[textureIndex]; }
void clear(ContextID contextID);
void set(ContextID contextID, size_t textureIndex, Texture *texture);
void reset(ContextID contextID, size_t textureIndex);
void clear();
void set(size_t textureIndex, Texture *texture);
void reset(size_t textureIndex);
bool empty() const;
private:
......
......@@ -99,6 +99,7 @@ TextureState::TextureState(TextureType type)
mBaseLevel(0),
mMaxLevel(kInitialMaxLevel),
mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
mHasBeenBoundAsImage(false),
mImmutableFormat(false),
mImmutableLevels(0),
mUsage(GL_NONE),
......@@ -2024,15 +2025,12 @@ angle::Result Texture::getTexImage(const Context *context,
pixels);
}
void Texture::onBindAsImageTexture(ContextID contextID)
void Texture::onBindAsImageTexture()
{
ContextBindingCount &bindingCount = mState.getBindingCount(contextID);
ASSERT(bindingCount.imageBindingCount < std::numeric_limits<uint32_t>::max());
mState.getBindingCount(contextID).imageBindingCount++;
if (bindingCount.imageBindingCount == 1)
if (!mState.mHasBeenBoundAsImage)
{
mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
mState.mHasBeenBoundAsImage = true;
}
}
......
......@@ -94,13 +94,6 @@ struct SwizzleState final
GLenum swizzleAlpha;
};
struct ContextBindingCount
{
ContextID contextID;
uint32_t samplerBindingCount;
uint32_t imageBindingCount;
};
// State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec.
class TextureState final : private angle::NonCopyable
{
......@@ -147,15 +140,7 @@ class TextureState final : private angle::NonCopyable
GLenum getDepthStencilTextureMode() const { return mDepthStencilTextureMode; }
bool isStencilMode() const { return mDepthStencilTextureMode == GL_STENCIL_INDEX; }
// TODO(jmadill): Remove. http://anglebug.com/4500
bool isBoundAsSamplerTexture(ContextID contextID) const
{
return getBindingCount(contextID).samplerBindingCount > 0;
}
bool isBoundAsImageTexture(ContextID contextID) const
{
return getBindingCount(contextID).imageBindingCount > 0;
}
bool hasBeenBoundAsImage() const { return mHasBeenBoundAsImage; }
gl::SrgbOverride getSRGBOverride() const { return mSrgbOverride; }
......@@ -173,8 +158,6 @@ class TextureState final : private angle::NonCopyable
// Return the enabled mipmap level count.
GLuint getEnabledLevelCount() const;
const std::vector<ContextBindingCount> &getBindingCounts() const { return mBindingCounts; }
bool getImmutableFormat() const { return mImmutableFormat; }
GLuint getImmutableLevels() const { return mImmutableLevels; }
......@@ -211,22 +194,6 @@ class TextureState final : private angle::NonCopyable
void clearImageDesc(TextureTarget target, size_t level);
void clearImageDescs();
ContextBindingCount &getBindingCount(ContextID contextID)
{
for (ContextBindingCount &bindingCount : mBindingCounts)
{
if (bindingCount.contextID == contextID)
return bindingCount;
}
mBindingCounts.push_back({contextID, 0, 0});
return mBindingCounts.back();
}
const ContextBindingCount &getBindingCount(ContextID contextID) const
{
return const_cast<TextureState *>(this)->getBindingCount(contextID);
}
const TextureType mType;
SwizzleState mSwizzleState;
......@@ -240,7 +207,7 @@ class TextureState final : private angle::NonCopyable
GLenum mDepthStencilTextureMode;
std::vector<ContextBindingCount> mBindingCounts;
bool mHasBeenBoundAsImage;
bool mImmutableFormat;
GLuint mImmutableLevels;
......@@ -474,37 +441,7 @@ class Texture final : public RefCountObject<TextureID>,
angle::Result generateMipmap(Context *context);
void onBindAsImageTexture(ContextID contextID);
ANGLE_INLINE void onUnbindAsImageTexture(ContextID contextID)
{
ASSERT(mState.isBoundAsImageTexture(contextID));
mState.getBindingCount(contextID).imageBindingCount--;
}
ANGLE_INLINE void onBindAsSamplerTexture(ContextID contextID)
{
ContextBindingCount &bindingCount = mState.getBindingCount(contextID);
ASSERT(bindingCount.samplerBindingCount < std::numeric_limits<uint32_t>::max());
bindingCount.samplerBindingCount++;
if (bindingCount.samplerBindingCount == 1)
{
onStateChange(angle::SubjectMessage::BindingChanged);
}
}
ANGLE_INLINE void onUnbindAsSamplerTexture(ContextID contextID)
{
ContextBindingCount &bindingCount = mState.getBindingCount(contextID);
ASSERT(mState.isBoundAsSamplerTexture(contextID));
bindingCount.samplerBindingCount--;
if (bindingCount.samplerBindingCount == 0)
{
onStateChange(angle::SubjectMessage::BindingChanged);
}
}
void onBindAsImageTexture();
egl::Surface *getBoundSurface() const;
egl::Stream *getBoundStream() const;
......
......@@ -811,14 +811,6 @@ void SerializeImageDesc(gl::BinaryOutputStream *bos, const gl::ImageDesc &imageD
bos->writeEnum(imageDesc.initState);
}
void SerializeContextBindingCount(gl::BinaryOutputStream *bos,
const gl::ContextBindingCount &contextBindingCount)
{
bos->writeInt(contextBindingCount.contextID);
bos->writeInt(contextBindingCount.imageBindingCount);
bos->writeInt(contextBindingCount.samplerBindingCount);
}
void SerializeTextureState(gl::BinaryOutputStream *bos, const gl::TextureState &textureState)
{
bos->writeEnum(textureState.getType());
......@@ -828,12 +820,7 @@ void SerializeTextureState(gl::BinaryOutputStream *bos, const gl::TextureState &
bos->writeInt(textureState.getBaseLevel());
bos->writeInt(textureState.getMaxLevel());
bos->writeInt(textureState.getDepthStencilTextureMode());
const std::vector<gl::ContextBindingCount> &contextBindingCounts =
textureState.getBindingCounts();
for (const gl::ContextBindingCount &contextBindingCount : contextBindingCounts)
{
SerializeContextBindingCount(bos, contextBindingCount);
}
bos->writeInt(textureState.hasBeenBoundAsImage());
bos->writeInt(textureState.getImmutableFormat());
bos->writeInt(textureState.getImmutableLevels());
bos->writeInt(textureState.getUsage());
......
......@@ -20,7 +20,7 @@ namespace rx
class MockFramebufferImpl : public rx::FramebufferImpl
{
public:
MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState(1, rx::Serial())) {}
MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState(rx::Serial())) {}
virtual ~MockFramebufferImpl() { destructor(); }
MOCK_METHOD3(discard, angle::Result(const gl::Context *, size_t, const GLenum *));
......
......@@ -1379,7 +1379,7 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
// Select the appropriate vk::ImageLayout depending on whether the texture is also bound as
// a GL image, and whether the program is a compute or graphics shader.
vk::ImageLayout textureLayout;
if (textureVk->isBoundAsImageTexture(mState.getContextID()))
if (textureVk->hasBeenBoundAsImage())
{
textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
: vk::ImageLayout::AllGraphicsShadersWrite;
......
......@@ -81,13 +81,13 @@ bool SharedGarbage::destroyIfComplete(RendererVk *renderer, Serial completedSeri
if (mLifetime.isCurrentlyInUse(completedSerial))
return false;
mLifetime.release();
for (GarbageObject &object : mGarbage)
{
object.destroy(renderer);
}
mLifetime.release();
return true;
}
......
......@@ -2172,6 +2172,9 @@ angle::Result TextureVk::syncState(const gl::Context *context,
ANGLE_TRY(initImageViews(contextVk, mImage->getFormat(), baseLevelDesc.format.info->sized,
mImage->getLevelCount(), layerCount));
// Let any Framebuffers know we need to refresh the RenderTarget cache.
onStateChange(angle::SubjectMessage::SubjectChanged);
}
vk::SamplerDesc samplerDesc(mState.getSamplerState(), mState.isStencilMode(),
......
......@@ -212,10 +212,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
GLenum type,
void *pixels) override;
ANGLE_INLINE bool isBoundAsImageTexture(gl::ContextID contextID) const
{
return mState.isBoundAsImageTexture(contextID);
}
ANGLE_INLINE bool hasBeenBoundAsImage() const { return mState.hasBeenBoundAsImage(); }
private:
// Transform an image index from the frontend into one that can be used on the backing
......
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