Commit e02a6834 by Jamie Madill Committed by Commit Bot

Refactor how we signal dependent state changes.

Dependent state changes happen when the user calls TexImage on a Texture attached to a Framebuffer. The Framebuffer should be told 'hey, you should know about this'. Other objects also have dependent relationships, like VertexArrays and Buffers. This refactoring uses a binding pointer design, similar to the type 'RefCountObject'. This design fixes the need for manual decoupling when one or the other is destroyed. The pointers are cleaned up in destructors, and do no-ops when either the source or dest is missing. Also move these new classes to a location where they are accessible to the GL layer; they will be important for framebuffer completeness. BUG=angleproject:1388 Change-Id: I92610acb85dae6f9c009b8f071e121fde53782ae Reviewed-on: https://chromium-review.googlesource.com/348953Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent d2b50a0b
...@@ -118,7 +118,9 @@ class Buffer11::BufferStorage : angle::NonCopyable ...@@ -118,7 +118,9 @@ class Buffer11::BufferStorage : angle::NonCopyable
class Buffer11::NativeStorage : public Buffer11::BufferStorage class Buffer11::NativeStorage : public Buffer11::BufferStorage
{ {
public: public:
NativeStorage(Renderer11 *renderer, BufferUsage usage, const NotificationSet *onStorageChanged); NativeStorage(Renderer11 *renderer,
BufferUsage usage,
const angle::BroadcastChannel *onStorageChanged);
~NativeStorage() override; ~NativeStorage() override;
bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
...@@ -143,7 +145,7 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage ...@@ -143,7 +145,7 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
unsigned int bufferSize); unsigned int bufferSize);
ID3D11Buffer *mNativeStorage; ID3D11Buffer *mNativeStorage;
const NotificationSet *mOnStorageChanged; const angle::BroadcastChannel *mOnStorageChanged;
}; };
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data // A emulated indexed buffer storage represents an underlying D3D11 buffer for data
...@@ -666,7 +668,7 @@ Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage) ...@@ -666,7 +668,7 @@ Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
case BUFFER_USAGE_EMULATED_INDEXED_VERTEX: case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
return new EmulatedIndexedStorage(mRenderer); return new EmulatedIndexedStorage(mRenderer);
case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
return new NativeStorage(mRenderer, usage, &mDirectBufferDirtyCallbacks); return new NativeStorage(mRenderer, usage, &mDirectBroadcastChannel);
default: default:
return new NativeStorage(mRenderer, usage, nullptr); return new NativeStorage(mRenderer, usage, nullptr);
} }
...@@ -822,7 +824,7 @@ void Buffer11::initializeStaticData() ...@@ -822,7 +824,7 @@ void Buffer11::initializeStaticData()
BufferD3D::initializeStaticData(); BufferD3D::initializeStaticData();
// Notify when static data changes. // Notify when static data changes.
mStaticBufferDirtyCallbacks.signal(); mStaticBroadcastChannel.signal();
} }
void Buffer11::invalidateStaticData() void Buffer11::invalidateStaticData()
...@@ -830,27 +832,17 @@ void Buffer11::invalidateStaticData() ...@@ -830,27 +832,17 @@ void Buffer11::invalidateStaticData()
BufferD3D::invalidateStaticData(); BufferD3D::invalidateStaticData();
// Notify when static data changes. // Notify when static data changes.
mStaticBufferDirtyCallbacks.signal(); mStaticBroadcastChannel.signal();
} }
void Buffer11::addStaticBufferDirtyCallback(const NotificationCallback *callback) angle::BroadcastChannel *Buffer11::getStaticBroadcastChannel()
{ {
mStaticBufferDirtyCallbacks.add(callback); return &mStaticBroadcastChannel;
} }
void Buffer11::removeStaticBufferDirtyCallback(const NotificationCallback *callback) angle::BroadcastChannel *Buffer11::getDirectBroadcastChannel()
{ {
mStaticBufferDirtyCallbacks.remove(callback); return &mDirectBroadcastChannel;
}
void Buffer11::addDirectBufferDirtyCallback(const NotificationCallback *callback)
{
mDirectBufferDirtyCallbacks.add(callback);
}
void Buffer11::removeDirectBufferDirtyCallback(const NotificationCallback *callback)
{
mDirectBufferDirtyCallbacks.remove(callback);
} }
Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
...@@ -874,7 +866,7 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s ...@@ -874,7 +866,7 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s
Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
BufferUsage usage, BufferUsage usage,
const NotificationSet *onStorageChanged) const angle::BroadcastChannel *onStorageChanged)
: BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged) : BufferStorage(renderer, usage), mNativeStorage(nullptr), mOnStorageChanged(onStorageChanged)
{ {
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/signal_utils.h"
namespace gl namespace gl
{ {
...@@ -79,14 +79,11 @@ class Buffer11 : public BufferD3D ...@@ -79,14 +79,11 @@ class Buffer11 : public BufferD3D
gl::Error unmap(GLboolean *result) override; gl::Error unmap(GLboolean *result) override;
gl::Error markTransformFeedbackUsage() override; gl::Error markTransformFeedbackUsage() override;
// We use two set of dirty callbacks for two events. Static buffers are marked dirty whenever // We use two set of dirty events. Static buffers are marked dirty whenever
// the data is changed, because they must be re-translated. Direct buffers only need to be // data changes, because they must be re-translated. Direct buffers only need to be
// updated when the underlying ID3D11Buffer pointer changes - hopefully far less often. // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often.
void addStaticBufferDirtyCallback(const NotificationCallback *callback); angle::BroadcastChannel *getStaticBroadcastChannel();
void removeStaticBufferDirtyCallback(const NotificationCallback *callback); angle::BroadcastChannel *getDirectBroadcastChannel();
void addDirectBufferDirtyCallback(const NotificationCallback *callback);
void removeDirectBufferDirtyCallback(const NotificationCallback *callback);
private: private:
class BufferStorage; class BufferStorage;
...@@ -139,8 +136,8 @@ class Buffer11 : public BufferD3D ...@@ -139,8 +136,8 @@ class Buffer11 : public BufferD3D
unsigned int mReadUsageCount; unsigned int mReadUsageCount;
unsigned int mSystemMemoryDeallocThreshold; unsigned int mSystemMemoryDeallocThreshold;
NotificationSet mStaticBufferDirtyCallbacks; angle::BroadcastChannel mStaticBroadcastChannel;
NotificationSet mDirectBufferDirtyCallbacks; angle::BroadcastChannel mDirectBroadcastChannel;
}; };
} // namespace rx } // namespace rx
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Texture.h" #include "libANGLE/Texture.h"
using namespace angle;
namespace rx namespace rx
{ {
...@@ -56,7 +58,7 @@ gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachme ...@@ -56,7 +58,7 @@ gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachme
void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment, void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment,
RenderTarget11 *&cachedRenderTarget, RenderTarget11 *&cachedRenderTarget,
const NotificationCallback &callbackFunc) ChannelBinding *channelBinding)
{ {
RenderTarget11 *newRenderTarget = nullptr; RenderTarget11 *newRenderTarget = nullptr;
if (attachment) if (attachment)
...@@ -65,54 +67,30 @@ void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment, ...@@ -65,54 +67,30 @@ void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment,
} }
if (newRenderTarget != cachedRenderTarget) if (newRenderTarget != cachedRenderTarget)
{ {
if (cachedRenderTarget) auto channel = (newRenderTarget ? newRenderTarget->getBroadcastChannel() : nullptr);
{ channelBinding->bind(channel);
cachedRenderTarget->removeDirtyCallback(&callbackFunc);
}
if (newRenderTarget)
{
newRenderTarget->addDirtyCallback(&callbackFunc);
}
cachedRenderTarget = newRenderTarget; cachedRenderTarget = newRenderTarget;
} }
} }
} // anonymous namespace } // anonymous namespace
Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer) Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer)
: FramebufferD3D(data, renderer), mRenderer(renderer), mCachedDepthStencilRenderTarget(nullptr) : FramebufferD3D(data, renderer),
mRenderer(renderer),
mCachedDepthStencilRenderTarget(nullptr),
mDepthStencilRenderTargetDirty(this, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
{ {
ASSERT(mRenderer != nullptr); ASSERT(mRenderer != nullptr);
mCachedColorRenderTargets.fill(nullptr); mCachedColorRenderTargets.fill(nullptr);
for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex) for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex)
{ {
auto callback = [this, colorIndex]() mColorRenderTargetsDirty.push_back(
{ ChannelBinding(this, static_cast<SignalToken>(colorIndex)));
this->markColorRenderTargetDirty(colorIndex);
};
mColorRenderTargetsDirty.push_back(callback);
} }
mDepthStencilRenderTargetDirty = [this]()
{
this->markDepthStencilRenderTargetDirty();
};
} }
Framebuffer11::~Framebuffer11() Framebuffer11::~Framebuffer11()
{ {
for (size_t colorIndex = 0; colorIndex < mCachedColorRenderTargets.size(); ++colorIndex)
{
auto *colorRenderTarget = mCachedColorRenderTargets[colorIndex];
if (colorRenderTarget)
{
colorRenderTarget->removeDirtyCallback(&mColorRenderTargetsDirty[colorIndex]);
}
}
if (mCachedDepthStencilRenderTarget)
{
mCachedDepthStencilRenderTarget->removeDirtyCallback(&mDepthStencilRenderTargetDirty);
}
} }
gl::Error Framebuffer11::invalidateSwizzles() const gl::Error Framebuffer11::invalidateSwizzles() const
...@@ -488,13 +466,13 @@ void Framebuffer11::updateColorRenderTarget(size_t colorIndex) ...@@ -488,13 +466,13 @@ void Framebuffer11::updateColorRenderTarget(size_t colorIndex)
{ {
UpdateCachedRenderTarget(mState.getColorAttachment(colorIndex), UpdateCachedRenderTarget(mState.getColorAttachment(colorIndex),
mCachedColorRenderTargets[colorIndex], mCachedColorRenderTargets[colorIndex],
mColorRenderTargetsDirty[colorIndex]); &mColorRenderTargetsDirty[colorIndex]);
} }
void Framebuffer11::updateDepthStencilRenderTarget() void Framebuffer11::updateDepthStencilRenderTarget()
{ {
UpdateCachedRenderTarget(mState.getDepthOrStencilAttachment(), mCachedDepthStencilRenderTarget, UpdateCachedRenderTarget(mState.getDepthOrStencilAttachment(), mCachedDepthStencilRenderTarget,
mDepthStencilRenderTargetDirty); &mDepthStencilRenderTargetDirty);
} }
void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
...@@ -504,7 +482,7 @@ void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) ...@@ -504,7 +482,7 @@ void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits; const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits;
mInternalDirtyBits.reset(); mInternalDirtyBits.reset();
for (auto dirtyBit : angle::IterateBitSet(mergedDirtyBits)) for (auto dirtyBit : IterateBitSet(mergedDirtyBits))
{ {
switch (dirtyBit) switch (dirtyBit)
{ {
...@@ -533,17 +511,19 @@ void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) ...@@ -533,17 +511,19 @@ void Framebuffer11::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
FramebufferD3D::syncState(dirtyBits); FramebufferD3D::syncState(dirtyBits);
} }
void Framebuffer11::markColorRenderTargetDirty(size_t colorIndex) void Framebuffer11::signal(SignalToken token)
{
mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
mCachedColorRenderTargets[colorIndex] = nullptr;
}
void Framebuffer11::markDepthStencilRenderTargetDirty()
{ {
// Stencil is redundant in this case. if (token == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT); {
mCachedDepthStencilRenderTarget = nullptr; // Stencil is redundant in this case.
mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT);
mCachedDepthStencilRenderTarget = nullptr;
}
else
{
mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + token);
mCachedColorRenderTargets[token] = nullptr;
}
} }
bool Framebuffer11::hasAnyInternalDirtyBit() const bool Framebuffer11::hasAnyInternalDirtyBit() const
......
...@@ -11,12 +11,13 @@ ...@@ -11,12 +11,13 @@
#include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/signal_utils.h"
namespace rx namespace rx
{ {
class Renderer11; class Renderer11;
class Framebuffer11 : public FramebufferD3D class Framebuffer11 : public FramebufferD3D, public angle::SignalReceiver
{ {
public: public:
Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer); Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer);
...@@ -40,13 +41,12 @@ class Framebuffer11 : public FramebufferD3D ...@@ -40,13 +41,12 @@ class Framebuffer11 : public FramebufferD3D
return mCachedDepthStencilRenderTarget; return mCachedDepthStencilRenderTarget;
} }
void markColorRenderTargetDirty(size_t colorIndex);
void markDepthStencilRenderTargetDirty();
bool hasAnyInternalDirtyBit() const; bool hasAnyInternalDirtyBit() const;
// TODO(jmadill): make this non-const // TODO(jmadill): make this non-const
void syncInternalState() const; void syncInternalState() const;
void signal(angle::SignalToken token) override;
private: private:
gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override; gl::Error clearImpl(ContextImpl *context, const ClearParameters &clearParams) override;
...@@ -77,8 +77,8 @@ class Framebuffer11 : public FramebufferD3D ...@@ -77,8 +77,8 @@ class Framebuffer11 : public FramebufferD3D
RenderTargetArray mCachedColorRenderTargets; RenderTargetArray mCachedColorRenderTargets;
RenderTarget11 *mCachedDepthStencilRenderTarget; RenderTarget11 *mCachedDepthStencilRenderTarget;
std::vector<NotificationCallback> mColorRenderTargetsDirty; std::vector<angle::ChannelBinding> mColorRenderTargetsDirty;
NotificationCallback mDepthStencilRenderTargetDirty; angle::ChannelBinding mDepthStencilRenderTargetDirty;
gl::Framebuffer::DirtyBits mInternalDirtyBits; gl::Framebuffer::DirtyBits mInternalDirtyBits;
}; };
......
...@@ -187,22 +187,12 @@ RenderTarget11::~RenderTarget11() ...@@ -187,22 +187,12 @@ RenderTarget11::~RenderTarget11()
signalDirty(); signalDirty();
} }
void RenderTarget11::addDirtyCallback(const NotificationCallback *callback)
{
mDirtyCallbacks.add(callback);
}
void RenderTarget11::removeDirtyCallback(const NotificationCallback *callback)
{
mDirtyCallbacks.remove(callback);
}
void RenderTarget11::signalDirty() void RenderTarget11::signalDirty()
{ {
mDirtyCallbacks.signal(); mBroadcastChannel.signal();
// Clear the signal list. We can't do this in the callback because it mutates the iterator. // Clear the list. We can't do this in the receiver because it would mutate during iteration.
mDirtyCallbacks.clear(); mBroadcastChannel.reset();
} }
TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv,
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
#include "libANGLE/renderer/d3d/RenderTargetD3D.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/signal_utils.h"
namespace rx namespace rx
{ {
...@@ -34,14 +34,13 @@ class RenderTarget11 : public RenderTargetD3D ...@@ -34,14 +34,13 @@ class RenderTarget11 : public RenderTargetD3D
virtual unsigned int getSubresourceIndex() const = 0; virtual unsigned int getSubresourceIndex() const = 0;
void addDirtyCallback(const NotificationCallback *callback);
void removeDirtyCallback(const NotificationCallback *callback);
void signalDirty() override; void signalDirty() override;
angle::BroadcastChannel *getBroadcastChannel() { return &mBroadcastChannel; }
d3d11::ANGLEFormat getANGLEFormat() const { return mANGLEFormat; } d3d11::ANGLEFormat getANGLEFormat() const { return mANGLEFormat; }
protected: protected:
NotificationSet mDirtyCallbacks; angle::BroadcastChannel mBroadcastChannel;
d3d11::ANGLEFormat mANGLEFormat; d3d11::ANGLEFormat mANGLEFormat;
}; };
...@@ -132,6 +131,6 @@ class SurfaceRenderTarget11 : public RenderTarget11 ...@@ -132,6 +131,6 @@ class SurfaceRenderTarget11 : public RenderTarget11
bool mDepth; bool mDepth;
}; };
} } // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "common/BitSetIterator.h" #include "common/BitSetIterator.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
using namespace angle;
namespace rx namespace rx
{ {
...@@ -45,11 +47,7 @@ VertexArray11::VertexArray11(const gl::VertexArrayState &data) ...@@ -45,11 +47,7 @@ VertexArray11::VertexArray11(const gl::VertexArrayState &data)
{ {
for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex) for (size_t attribIndex = 0; attribIndex < mCurrentBuffers.size(); ++attribIndex)
{ {
auto callback = [this, attribIndex]() mOnBufferDataDirty.push_back(ChannelBinding(this, static_cast<SignalToken>(attribIndex)));
{
this->markBufferDataDirty(attribIndex);
};
mOnBufferDataDirty.push_back(callback);
} }
} }
...@@ -59,7 +57,6 @@ VertexArray11::~VertexArray11() ...@@ -59,7 +57,6 @@ VertexArray11::~VertexArray11()
{ {
if (mCurrentBuffers[attribIndex].get()) if (mCurrentBuffers[attribIndex].get())
{ {
unlinkBuffer(attribIndex, mAttributeStorageTypes[attribIndex]);
mCurrentBuffers[attribIndex].set(nullptr); mCurrentBuffers[attribIndex].set(nullptr);
} }
} }
...@@ -116,22 +113,23 @@ void VertexArray11::updateVertexAttribStorage(size_t attribIndex) ...@@ -116,22 +113,23 @@ void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
{ {
// Note that for static callbacks, promotion to a static buffer from a dynamic buffer means // Note that for static callbacks, promotion to a static buffer from a dynamic buffer means
// we need to tag dynamic buffers with static callbacks. // we need to tag dynamic buffers with static callbacks.
if (oldBuffer11 != nullptr) BroadcastChannel *newChannel = nullptr;
{
unlinkBuffer(attribIndex, oldStorageType);
}
if (newBuffer11 != nullptr) if (newBuffer11 != nullptr)
{ {
if (newStorageType == VertexStorageType::DIRECT) switch (newStorageType)
{
newBuffer11->addDirectBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
else if (newStorageType == VertexStorageType::STATIC ||
newStorageType == VertexStorageType::DYNAMIC)
{ {
newBuffer11->addStaticBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]); case VertexStorageType::DIRECT:
newChannel = newBuffer11->getDirectBroadcastChannel();
break;
case VertexStorageType::STATIC:
case VertexStorageType::DYNAMIC:
newChannel = newBuffer11->getStaticBroadcastChannel();
break;
default:
break;
} }
} }
mOnBufferDataDirty[attribIndex].bind(newChannel);
mCurrentBuffers[attribIndex] = attrib.buffer; mCurrentBuffers[attribIndex] = attrib.buffer;
} }
} }
...@@ -230,12 +228,12 @@ const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() co ...@@ -230,12 +228,12 @@ const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() co
return mTranslatedAttribs; return mTranslatedAttribs;
} }
void VertexArray11::markBufferDataDirty(size_t attribIndex) void VertexArray11::signal(SignalToken token)
{ {
ASSERT(mAttributeStorageTypes[attribIndex] != VertexStorageType::CURRENT_VALUE); ASSERT(mAttributeStorageTypes[token] != VertexStorageType::CURRENT_VALUE);
// This can change a buffer's storage, we'll need to re-check. // This can change a buffer's storage, we'll need to re-check.
mAttribsToUpdate.set(attribIndex); mAttribsToUpdate.set(token);
} }
void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count) void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count)
...@@ -248,18 +246,4 @@ void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, G ...@@ -248,18 +246,4 @@ void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, G
auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count); VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count);
} }
void VertexArray11::unlinkBuffer(size_t attribIndex, VertexStorageType storageType)
{
Buffer11 *buffer = GetImplAs<Buffer11>(mCurrentBuffers[attribIndex].get());
if (storageType == VertexStorageType::DIRECT)
{
buffer->removeDirectBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
else if (storageType == VertexStorageType::STATIC || storageType == VertexStorageType::DYNAMIC)
{
buffer->removeStaticBufferDirtyCallback(&mOnBufferDataDirty[attribIndex]);
}
}
} // namespace rx } // namespace rx
...@@ -11,12 +11,13 @@ ...@@ -11,12 +11,13 @@
#include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/VertexArrayImpl.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/signal_utils.h"
namespace rx namespace rx
{ {
class Renderer11; class Renderer11;
class VertexArray11 : public VertexArrayImpl class VertexArray11 : public VertexArrayImpl, public angle::SignalReceiver
{ {
public: public:
VertexArray11(const gl::VertexArrayState &data); VertexArray11(const gl::VertexArrayState &data);
...@@ -32,10 +33,11 @@ class VertexArray11 : public VertexArrayImpl ...@@ -32,10 +33,11 @@ class VertexArray11 : public VertexArrayImpl
const std::vector<TranslatedAttribute> &getTranslatedAttribs() const; const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
// SignalReceiver implementation
void signal(angle::SignalToken token) override;
private: private:
void updateVertexAttribStorage(size_t attribIndex); void updateVertexAttribStorage(size_t attribIndex);
void markBufferDataDirty(size_t attribIndex);
void unlinkBuffer(size_t attribIndex, VertexStorageType storageType);
std::vector<VertexStorageType> mAttributeStorageTypes; std::vector<VertexStorageType> mAttributeStorageTypes;
std::vector<TranslatedAttribute> mTranslatedAttribs; std::vector<TranslatedAttribute> mTranslatedAttribs;
...@@ -52,7 +54,7 @@ class VertexArray11 : public VertexArrayImpl ...@@ -52,7 +54,7 @@ class VertexArray11 : public VertexArrayImpl
// We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks. // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers; std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers;
std::vector<NotificationCallback> mOnBufferDataDirty; std::vector<angle::ChannelBinding> mOnBufferDataDirty;
}; };
} // namespace rx } // namespace rx
......
...@@ -1724,40 +1724,4 @@ bool UsePresentPathFast(const Renderer11 *renderer, ...@@ -1724,40 +1724,4 @@ bool UsePresentPathFast(const Renderer11 *renderer,
renderer->presentPathFastEnabled()); renderer->presentPathFastEnabled());
} }
NotificationSet::NotificationSet()
{
}
NotificationSet::~NotificationSet()
{
}
void NotificationSet::add(const NotificationCallback *callback)
{
ASSERT(mCallbacks.count(callback) == 0);
mCallbacks.insert(callback);
}
void NotificationSet::remove(const NotificationCallback *callback)
{
ASSERT(mCallbacks.count(callback) == 1);
mCallbacks.erase(callback);
}
void NotificationSet::signal() const
{
if (mCallbacks.empty())
return;
for (const auto *callback : mCallbacks)
{
(*callback)();
}
}
void NotificationSet::clear()
{
mCallbacks.clear();
}
} // namespace rx } // namespace rx
...@@ -404,23 +404,6 @@ gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType, ...@@ -404,23 +404,6 @@ gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer); bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
using NotificationCallback = std::function<void()>;
class NotificationSet final : angle::NonCopyable
{
public:
NotificationSet();
~NotificationSet();
void add(const NotificationCallback *callback);
void remove(const NotificationCallback *callback);
void signal() const;
void clear();
private:
std::set<const NotificationCallback *> mCallbacks;
};
} // namespace rx } // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// signal_utils:
// Helper classes for tracking dependent state changes between objects.
// These changes are signaled to the dependent class via channels.
#include "libANGLE/signal_utils.h"
#include "common/debug.h"
namespace angle
{
BroadcastChannel::BroadcastChannel()
{
}
BroadcastChannel::~BroadcastChannel()
{
reset();
}
void BroadcastChannel::addReceiver(ChannelBinding *receiver)
{
ASSERT(mReceivers.count(receiver) == 0);
mReceivers.insert(receiver);
}
void BroadcastChannel::removeReceiver(ChannelBinding *receiver)
{
ASSERT(mReceivers.count(receiver) == 1);
mReceivers.erase(receiver);
}
void BroadcastChannel::signal() const
{
if (mReceivers.empty())
return;
for (const auto *receiver : mReceivers)
{
receiver->signal();
}
}
void BroadcastChannel::reset()
{
for (auto receiver : mReceivers)
{
receiver->onChannelClosed();
}
mReceivers.clear();
}
ChannelBinding::ChannelBinding(SignalReceiver *receiver, SignalToken token)
: mChannel(nullptr), mReceiver(receiver), mToken(token)
{
ASSERT(receiver);
}
ChannelBinding::~ChannelBinding()
{
reset();
}
void ChannelBinding::bind(BroadcastChannel *channel)
{
ASSERT(mReceiver);
if (mChannel)
{
mChannel->removeReceiver(this);
}
mChannel = channel;
if (mChannel)
{
mChannel->addReceiver(this);
}
}
void ChannelBinding::reset()
{
bind(nullptr);
}
void ChannelBinding::signal() const
{
mReceiver->signal(mToken);
}
void ChannelBinding::onChannelClosed()
{
mChannel = nullptr;
}
} // namespace angle
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// signal_utils:
// Helper classes for tracking dependent state changes between objects.
// These changes are signaled to the dependent class via channels.
#ifndef LIBANGLE_SIGNAL_UTILS_H_
#define LIBANGLE_SIGNAL_UTILS_H_
#include <set>
#include "common/angleutils.h"
namespace angle
{
// Message token passed to the receiver;
using SignalToken = uint32_t;
// Interface that the depending class inherits from.
class SignalReceiver
{
public:
virtual void signal(SignalToken token) = 0;
};
class ChannelBinding;
// The host class owns the channel. It uses the channel to fire signals to the receiver.
class BroadcastChannel final : NonCopyable
{
public:
BroadcastChannel();
~BroadcastChannel();
void signal() const;
void reset();
private:
// Only the ChannelBinding class should add or remove receivers.
friend class ChannelBinding;
void addReceiver(ChannelBinding *receiver);
void removeReceiver(ChannelBinding *receiver);
std::set<ChannelBinding *> mReceivers;
};
// The dependent class keeps bindings to the host's BroadcastChannel.
class ChannelBinding final
{
public:
ChannelBinding(SignalReceiver *receiver, SignalToken token);
~ChannelBinding();
ChannelBinding(const ChannelBinding &other) = default;
ChannelBinding &operator=(const ChannelBinding &other) = default;
void bind(BroadcastChannel *channel);
void reset();
void signal() const;
void onChannelClosed();
private:
BroadcastChannel *mChannel;
SignalReceiver *mReceiver;
SignalToken mToken;
};
} // namespace angle
#endif // LIBANGLE_SIGNAL_UTILS_H_
//
// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// signal_utils_unittest:
// Unit tests for signals and related utils.
#include <gtest/gtest.h>
#include "libANGLE/signal_utils.h"
using namespace angle;
using namespace testing;
namespace
{
struct SignalThing : public SignalReceiver
{
void signal(SignalToken token) override { wasSignaled = true; }
bool wasSignaled = false;
};
// Test that broadcast signals work.
TEST(SignalTest, BroadcastSignals)
{
BroadcastChannel channel;
SignalThing thing;
ChannelBinding binding(&thing, 0u);
binding.bind(&channel);
ASSERT_FALSE(thing.wasSignaled);
channel.signal();
ASSERT_TRUE(thing.wasSignaled);
}
} // anonymous namespace
...@@ -172,6 +172,8 @@ ...@@ -172,6 +172,8 @@
'libANGLE/renderer/imageformats.h', 'libANGLE/renderer/imageformats.h',
'libANGLE/renderer/renderer_utils.cpp', 'libANGLE/renderer/renderer_utils.cpp',
'libANGLE/renderer/renderer_utils.h', 'libANGLE/renderer/renderer_utils.h',
'libANGLE/signal_utils.cpp',
'libANGLE/signal_utils.h',
'libANGLE/validationEGL.cpp', 'libANGLE/validationEGL.cpp',
'libANGLE/validationEGL.h', 'libANGLE/validationEGL.h',
'libANGLE/validationES.cpp', 'libANGLE/validationES.cpp',
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
'<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp', '<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp',
'<(angle_path)/src/libANGLE/Surface_unittest.cpp', '<(angle_path)/src/libANGLE/Surface_unittest.cpp',
'<(angle_path)/src/libANGLE/TransformFeedback_unittest.cpp', '<(angle_path)/src/libANGLE/TransformFeedback_unittest.cpp',
'<(angle_path)/src/libANGLE/validationES_unittest.cpp',
'<(angle_path)/src/libANGLE/renderer/BufferImpl_mock.h', '<(angle_path)/src/libANGLE/renderer/BufferImpl_mock.h',
'<(angle_path)/src/libANGLE/renderer/FramebufferImpl_mock.h', '<(angle_path)/src/libANGLE/renderer/FramebufferImpl_mock.h',
'<(angle_path)/src/libANGLE/renderer/ProgramImpl_mock.h', '<(angle_path)/src/libANGLE/renderer/ProgramImpl_mock.h',
...@@ -38,6 +37,8 @@ ...@@ -38,6 +37,8 @@
'<(angle_path)/src/libANGLE/renderer/ImageImpl_mock.h', '<(angle_path)/src/libANGLE/renderer/ImageImpl_mock.h',
'<(angle_path)/src/libANGLE/renderer/TextureImpl_mock.h', '<(angle_path)/src/libANGLE/renderer/TextureImpl_mock.h',
'<(angle_path)/src/libANGLE/renderer/TransformFeedbackImpl_mock.h', '<(angle_path)/src/libANGLE/renderer/TransformFeedbackImpl_mock.h',
'<(angle_path)/src/libANGLE/signal_utils_unittest.cpp',
'<(angle_path)/src/libANGLE/validationES_unittest.cpp',
'<(angle_path)/src/tests/angle_unittests_utils.h', '<(angle_path)/src/tests/angle_unittests_utils.h',
'<(angle_path)/src/tests/compiler_tests/API_test.cpp', '<(angle_path)/src/tests/compiler_tests/API_test.cpp',
'<(angle_path)/src/tests/compiler_tests/BuiltInFunctionEmulator_test.cpp', '<(angle_path)/src/tests/compiler_tests/BuiltInFunctionEmulator_test.cpp',
......
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