Commit 0946393d by Jamie Madill Committed by Commit Bot

Move Buffer Subject/Observer to front end.

This makes BufferImpl into an Observer Subject. It also refactors the Vertex Array updates for the D3D11 backend use more of a dirty bit coding style. This change makes it so Buffer contents changes trigger front-end dirty bits from the back-end, which may be undesirable. Bug: angleproject:2389 Change-Id: Iac8ce1171284a86851c18cd1373ddf24fcefe40b Reviewed-on: https://chromium-review.googlesource.com/979812 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 59c5b897
...@@ -64,8 +64,7 @@ class BitSetT final ...@@ -64,8 +64,7 @@ class BitSetT final
}; };
BitSetT(); BitSetT();
BitSetT(BitsT value); constexpr explicit BitSetT(BitsT value);
~BitSetT();
BitSetT(const BitSetT &other); BitSetT(const BitSetT &other);
BitSetT &operator=(const BitSetT &other); BitSetT &operator=(const BitSetT &other);
...@@ -90,6 +89,10 @@ class BitSetT final ...@@ -90,6 +89,10 @@ class BitSetT final
BitSetT &operator^=(const BitSetT &other); BitSetT &operator^=(const BitSetT &other);
BitSetT operator~() const; BitSetT operator~() const;
BitSetT &operator&=(BitsT value);
BitSetT &operator|=(BitsT value);
BitSetT &operator^=(BitsT value);
BitSetT operator<<(std::size_t pos) const; BitSetT operator<<(std::size_t pos) const;
BitSetT &operator<<=(std::size_t pos); BitSetT &operator<<=(std::size_t pos);
BitSetT operator>>(std::size_t pos) const; BitSetT operator>>(std::size_t pos) const;
...@@ -115,6 +118,7 @@ class BitSetT final ...@@ -115,6 +118,7 @@ class BitSetT final
{ {
return (static_cast<BitsT>(1) << static_cast<size_t>(x)); return (static_cast<BitsT>(1) << static_cast<size_t>(x));
} }
// Produces a mask of ones up to the "x"th bit.
constexpr static BitsT Mask(std::size_t x) constexpr static BitsT Mask(std::size_t x)
{ {
return ((Bit(static_cast<ParamT>(x - 1)) - 1) << 1) + 1; return ((Bit(static_cast<ParamT>(x - 1)) - 1) << 1) + 1;
...@@ -216,12 +220,7 @@ BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0) ...@@ -216,12 +220,7 @@ BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
} }
template <size_t N, typename BitsT, typename ParamT> template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N)) constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
{
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::~BitSetT()
{ {
} }
...@@ -316,6 +315,27 @@ BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const ...@@ -316,6 +315,27 @@ BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
} }
template <size_t N, typename BitsT, typename ParamT> template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(BitsT value)
{
mBits &= value;
return *this;
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(BitsT value)
{
mBits |= value;
return *this;
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(BitsT value)
{
mBits ^= value;
return *this;
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
{ {
return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N)); return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N));
......
...@@ -88,6 +88,9 @@ Error Buffer::bufferData(const Context *context, ...@@ -88,6 +88,9 @@ Error Buffer::bufferData(const Context *context,
mState.mUsage = usage; mState.mUsage = usage;
mState.mSize = size; mState.mSize = size;
// Notify when data changes.
mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return NoError(); return NoError();
} }
...@@ -101,6 +104,9 @@ Error Buffer::bufferSubData(const Context *context, ...@@ -101,6 +104,9 @@ Error Buffer::bufferSubData(const Context *context,
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size)); mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
// Notify when data changes.
mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return NoError(); return NoError();
} }
...@@ -115,6 +121,9 @@ Error Buffer::copyBufferSubData(const Context *context, ...@@ -115,6 +121,9 @@ Error Buffer::copyBufferSubData(const Context *context,
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size)); mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
// Notify when data changes.
mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return NoError(); return NoError();
} }
...@@ -181,17 +190,26 @@ Error Buffer::unmap(const Context *context, GLboolean *result) ...@@ -181,17 +190,26 @@ Error Buffer::unmap(const Context *context, GLboolean *result)
mState.mAccess = GL_WRITE_ONLY_OES; mState.mAccess = GL_WRITE_ONLY_OES;
mState.mAccessFlags = 0; mState.mAccessFlags = 0;
// Notify when data changes.
mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return NoError(); return NoError();
} }
void Buffer::onTransformFeedback() void Buffer::onTransformFeedback(const Context *context)
{ {
mIndexRangeCache.clear(); mIndexRangeCache.clear();
// Notify when data changes.
mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
} }
void Buffer::onPixelUnpack() void Buffer::onPixelPack(const Context *context)
{ {
mIndexRangeCache.clear(); mIndexRangeCache.clear();
// Notify when data changes.
mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
} }
Error Buffer::getIndexRange(const gl::Context *context, Error Buffer::getIndexRange(const gl::Context *context,
......
...@@ -92,8 +92,9 @@ class Buffer final : public RefCountObject, public LabeledObject ...@@ -92,8 +92,9 @@ class Buffer final : public RefCountObject, public LabeledObject
Error mapRange(const Context *context, GLintptr offset, GLsizeiptr length, GLbitfield access); Error mapRange(const Context *context, GLintptr offset, GLsizeiptr length, GLbitfield access);
Error unmap(const Context *context, GLboolean *result); Error unmap(const Context *context, GLboolean *result);
void onTransformFeedback(); // These are called when another operation changes Buffer data.
void onPixelUnpack(); void onTransformFeedback(const Context *context);
void onPixelPack(const Context *context);
Error getIndexRange(const gl::Context *context, Error getIndexRange(const gl::Context *context,
GLenum type, GLenum type,
......
...@@ -129,13 +129,14 @@ gl::Error GetQueryObjectParameter(gl::Query *query, GLenum pname, T *params) ...@@ -129,13 +129,14 @@ gl::Error GetQueryObjectParameter(gl::Query *query, GLenum pname, T *params)
} }
} }
void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback, void MarkTransformFeedbackBufferUsage(const gl::Context *context,
gl::TransformFeedback *transformFeedback,
GLsizei count, GLsizei count,
GLsizei instanceCount) GLsizei instanceCount)
{ {
if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
{ {
transformFeedback->onVerticesDrawn(count, instanceCount); transformFeedback->onVerticesDrawn(context, count, instanceCount);
} }
} }
...@@ -1804,7 +1805,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) ...@@ -1804,7 +1805,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
ANGLE_CONTEXT_TRY(prepareForDraw()); ANGLE_CONTEXT_TRY(prepareForDraw());
ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count)); ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count));
MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback(), count, 1); MarkTransformFeedbackBufferUsage(this, mGLState.getCurrentTransformFeedback(), count, 1);
} }
void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
...@@ -1818,7 +1819,8 @@ void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz ...@@ -1818,7 +1819,8 @@ void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
ANGLE_CONTEXT_TRY(prepareForDraw()); ANGLE_CONTEXT_TRY(prepareForDraw());
ANGLE_CONTEXT_TRY( ANGLE_CONTEXT_TRY(
mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount)); mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount));
MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback(), count, instanceCount); MarkTransformFeedbackBufferUsage(this, mGLState.getCurrentTransformFeedback(), count,
instanceCount);
} }
void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
......
...@@ -1388,7 +1388,7 @@ Error Framebuffer::readPixels(const Context *context, ...@@ -1388,7 +1388,7 @@ Error Framebuffer::readPixels(const Context *context,
Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack); Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
if (unpackBuffer) if (unpackBuffer)
{ {
unpackBuffer->onPixelUnpack(); unpackBuffer->onPixelPack(context);
} }
return NoError(); return NoError();
......
...@@ -244,11 +244,11 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context, ...@@ -244,11 +244,11 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8, static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
"All bits of mAttributesTypeMask types and mask fit into 32 bits each"); "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
state->mAttributesTypeMask.from_ulong(stream.readInt<uint32_t>()); state->mAttributesTypeMask.from_ulong(stream.readInt<uint32_t>());
state->mAttributesMask = stream.readInt<uint32_t>(); state->mAttributesMask = stream.readInt<gl::AttributesMask>();
static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8, static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
"Too many vertex attribs for mask"); "Too many vertex attribs for mask");
state->mActiveAttribLocationsMask = stream.readInt<unsigned long>(); state->mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();
unsigned int attribCount = stream.readInt<unsigned int>(); unsigned int attribCount = stream.readInt<unsigned int>();
ASSERT(state->mAttributes.empty()); ASSERT(state->mAttributes.empty());
...@@ -390,7 +390,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context, ...@@ -390,7 +390,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
"All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit " "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
"into 32 bits each"); "into 32 bits each");
state->mDrawBufferTypeMask.from_ulong(stream.readInt<uint32_t>()); state->mDrawBufferTypeMask.from_ulong(stream.readInt<uint32_t>());
state->mActiveOutputVariables = stream.readInt<uint32_t>(); state->mActiveOutputVariables = stream.readInt<gl::DrawBufferMask>();
unsigned int samplerRangeLow = stream.readInt<unsigned int>(); unsigned int samplerRangeLow = stream.readInt<unsigned int>();
unsigned int samplerRangeHigh = stream.readInt<unsigned int>(); unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
...@@ -426,7 +426,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context, ...@@ -426,7 +426,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8, static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
"Too many shader types"); "Too many shader types");
state->mLinkedShaderStages = stream.readInt<unsigned long>(); state->mLinkedShaderStages = stream.readInt<gl::ShaderStagesMask>();
state->updateTransformFeedbackStrides(); state->updateTransformFeedbackStrides();
......
...@@ -2679,6 +2679,14 @@ void State::setFramebufferDirty(const Framebuffer *framebuffer) const ...@@ -2679,6 +2679,14 @@ void State::setFramebufferDirty(const Framebuffer *framebuffer) const
} }
} }
void State::setVertexArrayDirty(const VertexArray *vertexArray) const
{
if (vertexArray == mVertexArray)
{
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
}
void State::onProgramExecutableChange(Program *program) void State::onProgramExecutableChange(Program *program)
{ {
// OpenGL Spec: // OpenGL Spec:
......
...@@ -446,6 +446,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -446,6 +446,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable
Error syncDirtyObject(const Context *context, GLenum target); Error syncDirtyObject(const Context *context, GLenum target);
void setObjectDirty(GLenum target); void setObjectDirty(GLenum target);
void setFramebufferDirty(const Framebuffer *framebuffer) const; void setFramebufferDirty(const Framebuffer *framebuffer) const;
void setVertexArrayDirty(const VertexArray *vertexArray) const;
// This actually clears the current value dirty bits. // This actually clears the current value dirty bits.
// TODO(jmadill): Pass mutable dirty bits into Impl. // TODO(jmadill): Pass mutable dirty bits into Impl.
......
...@@ -191,7 +191,7 @@ bool TransformFeedback::checkBufferSpaceForDraw(GLsizei count, GLsizei primcount ...@@ -191,7 +191,7 @@ bool TransformFeedback::checkBufferSpaceForDraw(GLsizei count, GLsizei primcount
return vertices.IsValid() && vertices.ValueOrDie() <= mState.mVertexCapacity; return vertices.IsValid() && vertices.ValueOrDie() <= mState.mVertexCapacity;
} }
void TransformFeedback::onVerticesDrawn(GLsizei count, GLsizei primcount) void TransformFeedback::onVerticesDrawn(const Context *context, GLsizei count, GLsizei primcount)
{ {
ASSERT(mState.mActive && !mState.mPaused); ASSERT(mState.mActive && !mState.mPaused);
// All draws should be validated with checkBufferSpaceForDraw so ValueOrDie should never fail. // All draws should be validated with checkBufferSpaceForDraw so ValueOrDie should never fail.
...@@ -203,7 +203,7 @@ void TransformFeedback::onVerticesDrawn(GLsizei count, GLsizei primcount) ...@@ -203,7 +203,7 @@ void TransformFeedback::onVerticesDrawn(GLsizei count, GLsizei primcount)
{ {
if (buffer.get() != nullptr) if (buffer.get() != nullptr)
{ {
buffer->onTransformFeedback(); buffer->onTransformFeedback(context);
} }
} }
} }
......
...@@ -77,7 +77,7 @@ class TransformFeedback final : public RefCountObject, public LabeledObject ...@@ -77,7 +77,7 @@ class TransformFeedback final : public RefCountObject, public LabeledObject
// how many vertices have been written to the buffers. This information is needed by // how many vertices have been written to the buffers. This information is needed by
// checkBufferSpaceForDraw because each draw call appends vertices to the buffers starting just // checkBufferSpaceForDraw because each draw call appends vertices to the buffers starting just
// after the last vertex of the previous draw call. // after the last vertex of the previous draw call.
void onVerticesDrawn(GLsizei count, GLsizei primcount); void onVerticesDrawn(const Context *context, GLsizei count, GLsizei primcount);
bool hasBoundProgram(GLuint program) const; bool hasBoundProgram(GLuint program) const;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "libANGLE/VertexArray.h" #include "libANGLE/VertexArray.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/GLImplFactory.h" #include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/VertexArrayImpl.h"
...@@ -36,8 +37,13 @@ VertexArray::VertexArray(rx::GLImplFactory *factory, ...@@ -36,8 +37,13 @@ VertexArray::VertexArray(rx::GLImplFactory *factory,
size_t maxAttribBindings) size_t maxAttribBindings)
: mId(id), : mId(id),
mState(maxAttribs, maxAttribBindings), mState(maxAttribs, maxAttribBindings),
mVertexArray(factory->createVertexArray(mState)) mVertexArray(factory->createVertexArray(mState)),
mElementArrayBufferObserverBinding(this, maxAttribBindings)
{ {
for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
{
mArrayBufferObserverBindings.emplace_back(this, attribIndex);
}
} }
void VertexArray::onDestroy(const Context *context) void VertexArray::onDestroy(const Context *context)
...@@ -140,6 +146,8 @@ void VertexArray::bindVertexBufferImpl(const Context *context, ...@@ -140,6 +146,8 @@ void VertexArray::bindVertexBufferImpl(const Context *context,
binding->setBuffer(context, boundBuffer, isBound); binding->setBuffer(context, boundBuffer, isBound);
binding->setOffset(offset); binding->setOffset(offset);
binding->setStride(stride); binding->setStride(stride);
updateObserverBinding(bindingIndex);
} }
void VertexArray::bindVertexBuffer(const Context *context, void VertexArray::bindVertexBuffer(const Context *context,
...@@ -267,6 +275,7 @@ void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer) ...@@ -267,6 +275,7 @@ void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
mState.mElementArrayBuffer.set(context, buffer); mState.mElementArrayBuffer.set(context, buffer);
if (isBound && mState.mElementArrayBuffer.get()) if (isBound && mState.mElementArrayBuffer.get())
mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray); mState.mElementArrayBuffer->onBindingChanged(true, BufferBinding::ElementArray);
mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
} }
...@@ -274,9 +283,11 @@ gl::Error VertexArray::syncState(const Context *context) ...@@ -274,9 +283,11 @@ gl::Error VertexArray::syncState(const Context *context)
{ {
if (mDirtyBits.any()) if (mDirtyBits.any())
{ {
mDirtyBitsGuard = mDirtyBits;
ANGLE_TRY( ANGLE_TRY(
mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits)); mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
mDirtyBits.reset(); mDirtyBits.reset();
mDirtyBitsGuard.reset();
// This is a bit of an implementation hack - but since we know the implementation // This is a bit of an implementation hack - but since we know the implementation
// details of the dirty bit class it should always have the same effect as iterating // details of the dirty bit class it should always have the same effect as iterating
...@@ -298,4 +309,39 @@ void VertexArray::onBindingChanged(bool bound) ...@@ -298,4 +309,39 @@ void VertexArray::onBindingChanged(bool bound)
} }
} }
VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
angle::SubjectIndex index) const
{
if (index == mArrayBufferObserverBindings.size())
{
return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
: DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
}
else
{
// Note: this currently just gets the top-level dirty bit.
ASSERT(index < mArrayBufferObserverBindings.size());
return static_cast<DirtyBitType>(
(contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
}
}
void VertexArray::onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message)
{
bool contentsChanged = (message == angle::SubjectMessage::CONTENTS_CHANGED);
DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
mDirtyBits.set(dirtyBit);
context->getGLState().setVertexArrayDirty(this);
}
void VertexArray::updateObserverBinding(size_t bindingIndex)
{
Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
: nullptr);
}
} // namespace gl } // namespace gl
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "libANGLE/Constants.h" #include "libANGLE/Constants.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
#include "libANGLE/Observer.h"
#include "libANGLE/RefCountObject.h" #include "libANGLE/RefCountObject.h"
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "libANGLE/VertexAttribute.h" #include "libANGLE/VertexAttribute.h"
...@@ -72,7 +73,7 @@ class VertexArrayState final : angle::NonCopyable ...@@ -72,7 +73,7 @@ class VertexArrayState final : angle::NonCopyable
ComponentTypeMask mVertexAttributesTypeMask; ComponentTypeMask mVertexAttributesTypeMask;
}; };
class VertexArray final : public LabeledObject class VertexArray final : public angle::ObserverInterface, public LabeledObject
{ {
public: public:
VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings); VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings);
...@@ -153,6 +154,11 @@ class VertexArray final : public LabeledObject ...@@ -153,6 +154,11 @@ class VertexArray final : public LabeledObject
return mState.getEnabledAttributesMask(); return mState.getEnabledAttributesMask();
} }
// Observer implementation
void onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message) override;
// Dirty bits for VertexArrays use a heirarchical design. At the top level, each attribute // Dirty bits for VertexArrays use a heirarchical design. At the top level, each attribute
// has a single dirty bit. Then an array of MAX_ATTRIBS dirty bits each has a dirty bit for // has a single dirty bit. Then an array of MAX_ATTRIBS dirty bits each has a dirty bit for
// enabled/pointer/format/binding. Bindings are handled similarly. Note that because the // enabled/pointer/format/binding. Bindings are handled similarly. Note that because the
...@@ -162,6 +168,7 @@ class VertexArray final : public LabeledObject ...@@ -162,6 +168,7 @@ class VertexArray final : public LabeledObject
enum DirtyBitType enum DirtyBitType
{ {
DIRTY_BIT_ELEMENT_ARRAY_BUFFER, DIRTY_BIT_ELEMENT_ARRAY_BUFFER,
DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA,
// Dirty bits for attributes. // Dirty bits for attributes.
DIRTY_BIT_ATTRIB_0, DIRTY_BIT_ATTRIB_0,
...@@ -171,7 +178,11 @@ class VertexArray final : public LabeledObject ...@@ -171,7 +178,11 @@ class VertexArray final : public LabeledObject
DIRTY_BIT_BINDING_0 = DIRTY_BIT_ATTRIB_MAX, DIRTY_BIT_BINDING_0 = DIRTY_BIT_ATTRIB_MAX,
DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS, DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS,
DIRTY_BIT_UNKNOWN = DIRTY_BIT_BINDING_MAX, // We keep separate dirty bits for bound buffers whose data changed since last update.
DIRTY_BIT_BUFFER_DATA_0 = DIRTY_BIT_BINDING_MAX,
DIRTY_BIT_BUFFER_DATA_MAX = DIRTY_BIT_BUFFER_DATA_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS,
DIRTY_BIT_UNKNOWN = DIRTY_BIT_BUFFER_DATA_MAX,
DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN, DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
}; };
...@@ -218,14 +229,21 @@ class VertexArray final : public LabeledObject ...@@ -218,14 +229,21 @@ class VertexArray final : public LabeledObject
void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit); void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit); void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit);
void updateObserverBinding(size_t bindingIndex);
DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const;
GLuint mId; GLuint mId;
VertexArrayState mState; VertexArrayState mState;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
DirtyAttribBitsArray mDirtyAttribBits; DirtyAttribBitsArray mDirtyAttribBits;
DirtyBindingBitsArray mDirtyBindingBits; DirtyBindingBitsArray mDirtyBindingBits;
Optional<DirtyBits> mDirtyBitsGuard;
rx::VertexArrayImpl *mVertexArray; rx::VertexArrayImpl *mVertexArray;
std::vector<angle::ObserverBinding> mArrayBufferObserverBindings;
angle::ObserverBinding mElementArrayBufferObserverBinding;
}; };
} // namespace gl } // namespace gl
......
...@@ -19,7 +19,7 @@ using namespace gl; ...@@ -19,7 +19,7 @@ using namespace gl;
TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit) TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit)
{ {
VertexArray::DirtyBits dirtyBits; VertexArray::DirtyBits dirtyBits;
constexpr size_t bits[] = {1, 4, 9, 16, 25}; constexpr size_t bits[] = {1, 4, 9, 16, 25, 35};
constexpr GLint count = sizeof(bits) / sizeof(size_t); constexpr GLint count = sizeof(bits) / sizeof(size_t);
for (GLint i = 0; i < count; i++) for (GLint i = 0; i < count; i++)
{ {
...@@ -29,7 +29,11 @@ TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit) ...@@ -29,7 +29,11 @@ TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit)
for (size_t dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
const size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); const size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX) if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_0)
{
continue;
}
else if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX)
{ {
EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0, index); EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0, index);
} }
...@@ -37,6 +41,10 @@ TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit) ...@@ -37,6 +41,10 @@ TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit)
{ {
EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0, index); EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BINDING_0, index);
} }
else if (dirtyBit < VertexArray::DIRTY_BIT_BUFFER_DATA_MAX)
{
EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_BUFFER_DATA_0, index);
}
else else
ASSERT_TRUE(false); ASSERT_TRUE(false);
} }
......
...@@ -311,7 +311,7 @@ unsigned long ComponentTypeMask::to_ulong() const ...@@ -311,7 +311,7 @@ unsigned long ComponentTypeMask::to_ulong() const
void ComponentTypeMask::from_ulong(unsigned long mask) void ComponentTypeMask::from_ulong(unsigned long mask)
{ {
mTypeMask = mask; mTypeMask = angle::BitSet<MAX_COMPONENT_TYPE_MASK_INDEX * 2>(mask);
} }
bool ComponentTypeMask::Validate(unsigned long outputTypes, bool ComponentTypeMask::Validate(unsigned long outputTypes,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/mathutil.h" #include "common/mathutil.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/Observer.h"
#include "libANGLE/PackedGLEnums.h" #include "libANGLE/PackedGLEnums.h"
#include <stdint.h> #include <stdint.h>
...@@ -24,7 +25,10 @@ class Context; ...@@ -24,7 +25,10 @@ class Context;
namespace rx namespace rx
{ {
class BufferImpl : angle::NonCopyable // We use two set of Subject messages. The CONTENTS_CHANGED message is signaled whenever data
// changes, to trigger re-translation or other events. Some buffers only need to be updated when the
// underlying driver object changes - this is notified via the STORAGE_CHANGED message.
class BufferImpl : public angle::Subject
{ {
public: public:
BufferImpl(const gl::BufferState &state) : mState(state) {} BufferImpl(const gl::BufferState &state) : mState(state) {}
......
...@@ -153,7 +153,7 @@ VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib, ...@@ -153,7 +153,7 @@ VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib,
} }
// If specified with immediate data, we must use dynamic storage. // If specified with immediate data, we must use dynamic storage.
auto *buffer = binding.getBuffer().get(); gl::Buffer *buffer = binding.getBuffer().get();
if (!buffer) if (!buffer)
{ {
return VertexStorageType::DYNAMIC; return VertexStorageType::DYNAMIC;
......
...@@ -398,9 +398,6 @@ gl::Error Buffer11::setSubData(const gl::Context *context, ...@@ -398,9 +398,6 @@ gl::Error Buffer11::setSubData(const gl::Context *context,
ANGLE_TRY(writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size)); ANGLE_TRY(writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size));
onStorageUpdate(writeBuffer); onStorageUpdate(writeBuffer);
// Notify when data changes.
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
} }
mSize = std::max(mSize, requiredSize); mSize = std::max(mSize, requiredSize);
...@@ -470,9 +467,6 @@ gl::Error Buffer11::copySubData(const gl::Context *context, ...@@ -470,9 +467,6 @@ gl::Error Buffer11::copySubData(const gl::Context *context,
mSize = std::max<size_t>(mSize, destOffset + size); mSize = std::max<size_t>(mSize, destOffset + size);
invalidateStaticData(context); invalidateStaticData(context);
// Also notify that the contents are dirty.
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return gl::NoError(); return gl::NoError();
} }
......
...@@ -47,10 +47,7 @@ enum BufferUsage ...@@ -47,10 +47,7 @@ enum BufferUsage
typedef size_t DataRevision; typedef size_t DataRevision;
// We use two set of Subject messages. The CONTENTS_CHANGED message is signaled whenever data class Buffer11 : public BufferD3D
// changes, to trigger re-translation or other events. Some buffers only need to be updated when the
// underlying ID3D11Buffer object changes - this is notified via the STORAGE_CHANGED message.
class Buffer11 : public BufferD3D, public angle::Subject
{ {
public: public:
Buffer11(const gl::BufferState &state, Renderer11 *renderer); Buffer11(const gl::BufferState &state, Renderer11 *renderer);
......
...@@ -69,10 +69,22 @@ bool DrawCallHasStreamingElementArray(const gl::Context *context, GLenum srcType ...@@ -69,10 +69,22 @@ bool DrawCallHasStreamingElementArray(const gl::Context *context, GLenum srcType
: GL_UNSIGNED_SHORT; : GL_UNSIGNED_SHORT;
// Not clear where the offset comes from here. // Not clear where the offset comes from here.
bool needsTranslation = false; switch (ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0))
ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0, &needsTranslation); {
case IndexStorageType::Dynamic:
return needsTranslation; return true;
case IndexStorageType::Direct:
return false;
case IndexStorageType::Static:
{
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
return (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != dstType);
}
default:
UNREACHABLE();
return true;
}
} }
template <typename IndirectBufferT> template <typename IndirectBufferT>
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "libANGLE/renderer/d3d/IndexDataManager.h" #include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Context11.h" #include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
......
...@@ -1411,8 +1411,6 @@ gl::Error Renderer11::drawArrays(const gl::Context *context, const gl::DrawCallP ...@@ -1411,8 +1411,6 @@ gl::Error Renderer11::drawArrays(const gl::Context *context, const gl::DrawCallP
ANGLE_TRY(markTransformFeedbackUsage(context)); ANGLE_TRY(markTransformFeedbackUsage(context));
} }
ANGLE_TRY(mStateManager.applyVertexBuffer(context, params));
gl::Program *program = glState.getProgram(); gl::Program *program = glState.getProgram();
ASSERT(program != nullptr); ASSERT(program != nullptr);
GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, params.instances()); GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, params.instances());
...@@ -1535,12 +1533,6 @@ gl::Error Renderer11::drawElements(const gl::Context *context, const gl::DrawCal ...@@ -1535,12 +1533,6 @@ gl::Error Renderer11::drawElements(const gl::Context *context, const gl::DrawCal
const auto &glState = context->getGLState(); const auto &glState = context->getGLState();
ASSERT(!glState.isTransformFeedbackActiveUnpaused()); ASSERT(!glState.isTransformFeedbackActiveUnpaused());
bool usePrimitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), params.type());
ANGLE_TRY(mStateManager.applyIndexBuffer(context, params, usePrimitiveRestartWorkaround));
ANGLE_TRY(mStateManager.applyVertexBuffer(context, params));
// If this draw call is coming from an indirect call, offset by the indirect call's base vertex. // If this draw call is coming from an indirect call, offset by the indirect call's base vertex.
// No base vertex parameter exists for a normal drawElements, so params.baseVertex will be zero. // No base vertex parameter exists for a normal drawElements, so params.baseVertex will be zero.
int startVertex = static_cast<int>(params.firstVertex() - params.baseVertex()); int startVertex = static_cast<int>(params.firstVertex() - params.baseVertex());
...@@ -1623,8 +1615,6 @@ gl::Error Renderer11::drawArraysIndirect(const gl::Context *context, ...@@ -1623,8 +1615,6 @@ gl::Error Renderer11::drawArraysIndirect(const gl::Context *context,
const gl::State &glState = context->getGLState(); const gl::State &glState = context->getGLState();
ASSERT(!glState.isTransformFeedbackActiveUnpaused()); ASSERT(!glState.isTransformFeedbackActiveUnpaused());
ANGLE_TRY(mStateManager.applyVertexBuffer(context, params));
gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
ASSERT(drawIndirectBuffer); ASSERT(drawIndirectBuffer);
Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
...@@ -1653,11 +1643,6 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context, ...@@ -1653,11 +1643,6 @@ gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer); Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
uintptr_t offset = reinterpret_cast<uintptr_t>(params.indirect()); uintptr_t offset = reinterpret_cast<uintptr_t>(params.indirect());
bool usePrimitiveRestartWorkaround =
UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), params.type());
ANGLE_TRY(mStateManager.applyIndexBuffer(context, params, usePrimitiveRestartWorkaround));
ANGLE_TRY(mStateManager.applyVertexBuffer(context, params));
ID3D11Buffer *buffer = nullptr; ID3D11Buffer *buffer = nullptr;
ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer); ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset)); mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
......
...@@ -183,15 +183,18 @@ class StateManager11 final : angle::NonCopyable ...@@ -183,15 +183,18 @@ class StateManager11 final : angle::NonCopyable
// Called by the Framebuffer11 and VertexArray11. // Called by the Framebuffer11 and VertexArray11.
void invalidateShaders(); void invalidateShaders();
// Called by VertexArray11 to trigger attribute translation.
void invalidateVertexAttributeTranslation();
// Called by the Program on Uniform Buffer change. Also called internally. // Called by the Program on Uniform Buffer change. Also called internally.
void invalidateProgramUniformBuffers(); void invalidateProgramUniformBuffers();
// Called by TransformFeedback11. // Called by TransformFeedback11.
void invalidateTransformFeedback(); void invalidateTransformFeedback();
// Called by VertexArray11.
void invalidateInputLayout();
// Called by VertexArray11 element array buffer sync.
void invalidateIndexBuffer();
void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv); void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv); void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv);
...@@ -232,14 +235,6 @@ class StateManager11 final : angle::NonCopyable ...@@ -232,14 +235,6 @@ class StateManager11 final : angle::NonCopyable
void setSimpleScissorRect(const gl::Rectangle &glRect); void setSimpleScissorRect(const gl::Rectangle &glRect);
void setScissorRectD3D(const D3D11_RECT &d3dRect); void setScissorRectD3D(const D3D11_RECT &d3dRect);
// Not handled by an internal dirty bit because of the extra draw parameters.
gl::Error applyVertexBuffer(const gl::Context *context,
const gl::DrawCallParams &drawCallParams);
gl::Error applyIndexBuffer(const gl::Context *context,
const gl::DrawCallParams &drawCallParams,
bool usePrimitiveRestartWorkaround);
void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset); void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
...@@ -252,6 +247,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -252,6 +247,7 @@ class StateManager11 final : angle::NonCopyable
InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
GLsizei getCurrentMinimumDrawCount() const { return mCurrentMinimumDrawCount; } GLsizei getCurrentMinimumDrawCount() const { return mCurrentMinimumDrawCount; }
VertexDataManager *getVertexDataManager() { return &mVertexDataManager; }
private: private:
template <typename SRVType> template <typename SRVType>
...@@ -336,6 +332,8 @@ class StateManager11 final : angle::NonCopyable ...@@ -336,6 +332,8 @@ class StateManager11 final : angle::NonCopyable
void processFramebufferInvalidation(const gl::Context *context); void processFramebufferInvalidation(const gl::Context *context);
bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset); bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
gl::Error syncVertexBuffersAndInputLayout(const gl::Context *context,
const gl::DrawCallParams &vertexParams);
bool setInputLayoutInternal(const d3d11::InputLayout *inputLayout); bool setInputLayoutInternal(const d3d11::InputLayout *inputLayout);
...@@ -352,6 +350,10 @@ class StateManager11 final : angle::NonCopyable ...@@ -352,6 +350,10 @@ class StateManager11 final : angle::NonCopyable
ProgramD3D *programD3D, ProgramD3D *programD3D,
GLenum currentDrawMode); GLenum currentDrawMode);
// Not handled by an internal dirty bit because it isn't synced on drawArrays calls.
gl::Error applyIndexBuffer(const gl::Context *context,
const gl::DrawCallParams &drawCallParams);
enum DirtyBitType enum DirtyBitType
{ {
DIRTY_BIT_RENDER_TARGET, DIRTY_BIT_RENDER_TARGET,
...@@ -367,6 +369,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -367,6 +369,7 @@ class StateManager11 final : angle::NonCopyable
DIRTY_BIT_SHADERS, DIRTY_BIT_SHADERS,
DIRTY_BIT_CURRENT_VALUE_ATTRIBS, DIRTY_BIT_CURRENT_VALUE_ATTRIBS,
DIRTY_BIT_TRANSFORM_FEEDBACK, DIRTY_BIT_TRANSFORM_FEEDBACK,
DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT,
DIRTY_BIT_PRIMITIVE_TOPOLOGY, DIRTY_BIT_PRIMITIVE_TOPOLOGY,
DIRTY_BIT_INVALID, DIRTY_BIT_INVALID,
DIRTY_BIT_MAX = DIRTY_BIT_INVALID, DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
...@@ -475,8 +478,6 @@ class StateManager11 final : angle::NonCopyable ...@@ -475,8 +478,6 @@ class StateManager11 final : angle::NonCopyable
// Current applied input layout. // Current applied input layout.
ResourceSerial mCurrentInputLayout; ResourceSerial mCurrentInputLayout;
bool mInputLayoutIsDirty;
bool mVertexAttribsNeedTranslation;
// Current applied vertex states. // Current applied vertex states.
// TODO(jmadill): Figure out how to use ResourceSerial here. // TODO(jmadill): Figure out how to use ResourceSerial here.
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/Observer.h"
#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/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
...@@ -19,31 +18,28 @@ namespace rx ...@@ -19,31 +18,28 @@ namespace rx
{ {
class Renderer11; class Renderer11;
class VertexArray11 : public angle::ObserverInterface, public VertexArrayImpl class VertexArray11 : public VertexArrayImpl
{ {
public: public:
VertexArray11(const gl::VertexArrayState &data); VertexArray11(const gl::VertexArrayState &data);
~VertexArray11() override; ~VertexArray11() override;
void destroy(const gl::Context *context) override; void destroy(const gl::Context *context) override;
// Does not apply any state updates - these are done in syncStateForDraw which as access to
// the DrawCallParams before a draw.
gl::Error syncState(const gl::Context *context, gl::Error syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits, const gl::VertexArray::DirtyBits &dirtyBits,
const gl::VertexArray::DirtyAttribBitsArray &attribBits, const gl::VertexArray::DirtyAttribBitsArray &attribBits,
const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override; const gl::VertexArray::DirtyBindingBitsArray &bindingBits) override;
// This will flush any pending attrib updates and then check the dynamic attribs mask.
bool hasActiveDynamicAttrib(const gl::Context *context); // Applied buffer pointers are updated here.
gl::Error updateDirtyAndDynamicAttribs(const gl::Context *context, gl::Error syncStateForDraw(const gl::Context *context,
VertexDataManager *vertexDataManager,
const gl::DrawCallParams &drawCallParams);
void clearDirtyAndPromoteDynamicAttribs(const gl::Context *context,
const gl::DrawCallParams &drawCallParams); const gl::DrawCallParams &drawCallParams);
const std::vector<TranslatedAttribute> &getTranslatedAttribs() const; // This will check the dynamic attribs mask.
bool hasActiveDynamicAttrib(const gl::Context *context);
// Observer implementation const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
void onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message) override;
Serial getCurrentStateSerial() const { return mCurrentStateSerial; } Serial getCurrentStateSerial() const { return mCurrentStateSerial; }
...@@ -51,20 +47,25 @@ class VertexArray11 : public angle::ObserverInterface, public VertexArrayImpl ...@@ -51,20 +47,25 @@ class VertexArray11 : public angle::ObserverInterface, public VertexArrayImpl
// is adjusted. // is adjusted.
void markAllAttributeDivisorsForAdjustment(int numViews); void markAllAttributeDivisorsForAdjustment(int numViews);
bool flushAttribUpdates(const gl::Context *context);
// Returns true if the element array buffer needs to be translated. // Returns true if the element array buffer needs to be translated.
bool updateElementArrayStorage(const gl::Context *context, gl::Error updateElementArrayStorage(const gl::Context *context,
GLenum elementType, const gl::DrawCallParams &drawCallParams,
GLenum destElementType, bool restartEnabled);
const void *indices);
TranslatedIndexData *getCachedIndexInfo(); const TranslatedIndexData &getCachedIndexInfo() const;
void setCachedIndexInfoValid(); void updateCachedIndexInfo(const TranslatedIndexData &indexInfo);
bool isCachedIndexInfoValid() const; bool isCachedIndexInfoValid() const;
GLenum getCachedDestinationIndexType() const;
private: private:
void updateVertexAttribStorage(const gl::Context *context, size_t attribIndex); void updateVertexAttribStorage(StateManager11 *stateManager,
size_t dirtyBit,
size_t attribIndex);
gl::Error updateDirtyAttribs(const gl::Context *context);
gl::Error updateDynamicAttribs(const gl::Context *context,
VertexDataManager *vertexDataManager,
const gl::DrawCallParams &drawCallParams);
std::vector<VertexStorageType> mAttributeStorageTypes; std::vector<VertexStorageType> mAttributeStorageTypes;
std::vector<TranslatedAttribute> mTranslatedAttribs; std::vector<TranslatedAttribute> mTranslatedAttribs;
...@@ -72,30 +73,24 @@ class VertexArray11 : public angle::ObserverInterface, public VertexArrayImpl ...@@ -72,30 +73,24 @@ class VertexArray11 : public angle::ObserverInterface, public VertexArrayImpl
// The mask of attributes marked as dynamic. // The mask of attributes marked as dynamic.
gl::AttributesMask mDynamicAttribsMask; gl::AttributesMask mDynamicAttribsMask;
// A mask of attributes that need to be re-evaluated. // Mask applied to dirty bits on syncState. If a bit is on, it is relevant.
gl::AttributesMask mAttribsToUpdate; gl::VertexArray::DirtyBits mRelevantDirtyBitsMask;
// A set of attributes we know are dirty, and need to be re-translated. // A set of attributes we know are dirty, and need to be re-translated.
gl::AttributesMask mAttribsToTranslate; gl::AttributesMask mAttribsToTranslate;
// We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
std::vector<gl::BindingPointer<gl::Buffer>> mCurrentArrayBuffers;
gl::BindingPointer<gl::Buffer> mCurrentElementArrayBuffer;
std::vector<angle::ObserverBinding> mOnArrayBufferDataDirty;
angle::ObserverBinding mOnElementArrayBufferDataDirty;
Serial mCurrentStateSerial; Serial mCurrentStateSerial;
// The numViews value used to adjust the divisor. // The numViews value used to adjust the divisor.
int mAppliedNumViewsToDivisor; int mAppliedNumViewsToDivisor;
// If the index buffer needs re-streaming. // If the index buffer needs re-streaming.
GLenum mLastElementType; Optional<GLenum> mLastDrawElementsType;
unsigned int mLastDrawElementsOffset; Optional<const void *> mLastDrawElementsIndices;
Optional<bool> mLastPrimitiveRestartEnabled;
IndexStorageType mCurrentElementArrayStorage; IndexStorageType mCurrentElementArrayStorage;
TranslatedIndexData mCachedIndexInfo; Optional<TranslatedIndexData> mCachedIndexInfo;
bool mCachedIndexInfoValid; GLenum mCachedDestinationIndexType;
}; };
} // namespace rx } // namespace rx
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" #include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
...@@ -2362,13 +2361,11 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState, ...@@ -2362,13 +2361,11 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState,
const gl::Buffer *elementArrayBuffer, const gl::Buffer *elementArrayBuffer,
GLenum elementType, GLenum elementType,
GLenum destElementType, GLenum destElementType,
unsigned int offset, unsigned int offset)
bool *needsTranslation)
{ {
// No buffer bound means we are streaming from a client pointer. // No buffer bound means we are streaming from a client pointer.
if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset)) if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
{ {
*needsTranslation = true;
return IndexStorageType::Dynamic; return IndexStorageType::Dynamic;
} }
...@@ -2376,7 +2373,6 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState, ...@@ -2376,7 +2373,6 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState,
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer); BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
if (bufferD3D->supportsDirectBinding() && destElementType == elementType) if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
{ {
*needsTranslation = false;
return IndexStorageType::Direct; return IndexStorageType::Direct;
} }
...@@ -2384,15 +2380,10 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState, ...@@ -2384,15 +2380,10 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState,
StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer(); StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
if (staticBuffer != nullptr) if (staticBuffer != nullptr)
{ {
// Need to re-translate the static data if has never been used, or changed type.
*needsTranslation =
(staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != destElementType);
return IndexStorageType::Static; return IndexStorageType::Static;
} }
// Static buffer not available, fall back to streaming. // Static buffer not available, fall back to streaming.
*needsTranslation = true;
return IndexStorageType::Dynamic; return IndexStorageType::Dynamic;
} }
} // namespace rx } // namespace rx
...@@ -419,8 +419,7 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState, ...@@ -419,8 +419,7 @@ IndexStorageType ClassifyIndexStorage(const gl::State &glState,
const gl::Buffer *elementArrayBuffer, const gl::Buffer *elementArrayBuffer,
GLenum elementType, GLenum elementType,
GLenum destElementType, GLenum destElementType,
unsigned int offset, unsigned int offset);
bool *needsTranslation);
} // namespace rx } // namespace rx
......
...@@ -716,6 +716,9 @@ gl::Error VertexArrayGL::syncState(const gl::Context *context, ...@@ -716,6 +716,9 @@ gl::Error VertexArrayGL::syncState(const gl::Context *context,
updateElementArrayBufferBinding(context); updateElementArrayBufferBinding(context);
break; break;
case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
break;
default: default:
{ {
ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0); ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0);
...@@ -724,12 +727,16 @@ gl::Error VertexArrayGL::syncState(const gl::Context *context, ...@@ -724,12 +727,16 @@ gl::Error VertexArrayGL::syncState(const gl::Context *context,
{ {
syncDirtyAttrib(context, index, attribBits[index]); syncDirtyAttrib(context, index, attribBits[index]);
} }
else else if (dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX)
{ {
ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0 && ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0);
dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX);
syncDirtyBinding(context, index, bindingBits[index]); syncDirtyBinding(context, index, bindingBits[index]);
} }
else
{
ASSERT(dirtyBit >= VertexArray::DIRTY_BIT_BUFFER_DATA_0 &&
dirtyBit < VertexArray::DIRTY_BIT_BUFFER_DATA_MAX);
}
break; break;
} }
} }
...@@ -751,4 +758,4 @@ void VertexArrayGL::applyNumViewsToDivisor(int numViews) ...@@ -751,4 +758,4 @@ void VertexArrayGL::applyNumViewsToDivisor(int numViews)
} }
} }
} // rx } // namespace rx
...@@ -18,7 +18,7 @@ namespace rx ...@@ -18,7 +18,7 @@ namespace rx
{ {
class RendererVk; class RendererVk;
class BufferVk : public BufferImpl, public ResourceVk, public angle::Subject class BufferVk : public BufferImpl, public ResourceVk
{ {
public: public:
BufferVk(const gl::BufferState &state); BufferVk(const gl::BufferState &state);
......
...@@ -109,9 +109,11 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context, ...@@ -109,9 +109,11 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context,
const auto &attribs = mState.getVertexAttributes(); const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings(); const auto &bindings = mState.getVertexBindings();
for (auto dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) switch (dirtyBit)
{
case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
{ {
gl::Buffer *bufferGL = mState.getElementArrayBuffer().get(); gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
if (bufferGL) if (bufferGL)
...@@ -122,9 +124,14 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context, ...@@ -122,9 +124,14 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context,
{ {
mCurrentElementArrayBufferResource = nullptr; mCurrentElementArrayBufferResource = nullptr;
} }
continue; break;
} }
case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
break;
default:
{
size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
// Invalidate the input description for pipelines. // Invalidate the input description for pipelines.
...@@ -141,7 +148,8 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context, ...@@ -141,7 +148,8 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context,
{ {
BufferVk *bufferVk = vk::GetImpl(bufferGL); BufferVk *bufferVk = vk::GetImpl(bufferGL);
mCurrentArrayBufferResources[attribIndex] = bufferVk; mCurrentArrayBufferResources[attribIndex] = bufferVk;
mCurrentArrayBufferHandles[attribIndex] = bufferVk->getVkBuffer().getHandle(); mCurrentArrayBufferHandles[attribIndex] =
bufferVk->getVkBuffer().getHandle();
mClientMemoryAttribs.reset(attribIndex); mClientMemoryAttribs.reset(attribIndex);
} }
else else
...@@ -158,6 +166,9 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context, ...@@ -158,6 +166,9 @@ gl::Error VertexArrayVk::syncState(const gl::Context *context,
mClientMemoryAttribs.reset(attribIndex); mClientMemoryAttribs.reset(attribIndex);
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
break;
}
}
} }
return gl::NoError(); return gl::NoError();
......
...@@ -1414,7 +1414,7 @@ void LineLoopHandler::onSubjectStateChange(const gl::Context *context, ...@@ -1414,7 +1414,7 @@ void LineLoopHandler::onSubjectStateChange(const gl::Context *context,
angle::SubjectMessage message) angle::SubjectMessage message)
{ {
// Indicate we want to recopy on next draw since something changed in the buffer. // Indicate we want to recopy on next draw since something changed in the buffer.
if (message == angle::SubjectMessage::STORAGE_CHANGED) if (message == angle::SubjectMessage::CONTENTS_CHANGED)
{ {
mLineLoopIndexBuffer = VK_NULL_HANDLE; mLineLoopIndexBuffer = VK_NULL_HANDLE;
} }
......
...@@ -339,7 +339,7 @@ TEST_P(IndexedBufferCopyTest, IndexRangeBug) ...@@ -339,7 +339,7 @@ TEST_P(IndexedBufferCopyTest, IndexRangeBug)
glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
class BufferDataTestES3 : public BufferDataTest class BufferDataTestES3 : public BufferDataTest
......
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