summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp347
1 files changed, 154 insertions, 193 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
index 9efee9db7c..7c2d5aec70 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -8,18 +8,19 @@
// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+#include "common/mathutil.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/VertexAttribute.h"
-#include "common/mathutil.h"
-
namespace rx
{
+// VertexBuffer Implementation
unsigned int VertexBuffer::mNextSerial = 1;
-VertexBuffer::VertexBuffer()
+VertexBuffer::VertexBuffer() : mRefCount(1)
{
updateSerial();
}
@@ -38,19 +39,34 @@ unsigned int VertexBuffer::getSerial() const
return mSerial;
}
-VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
- : mFactory(factory)
+void VertexBuffer::addRef()
{
- mDynamic = dynamic;
- mWritePosition = 0;
- mReservedSpace = 0;
+ mRefCount++;
+}
+
+void VertexBuffer::release()
+{
+ ASSERT(mRefCount > 0);
+ mRefCount--;
+
+ if (mRefCount == 0)
+ {
+ delete this;
+ }
+}
- mVertexBuffer = factory->createVertexBuffer();
+// VertexBufferInterface Implementation
+VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+ : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic)
+{
}
VertexBufferInterface::~VertexBufferInterface()
{
- delete mVertexBuffer;
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->release();
+ }
}
unsigned int VertexBufferInterface::getSerial() const
@@ -69,181 +85,172 @@ gl::Error VertexBufferInterface::setBufferSize(unsigned int size)
{
return mVertexBuffer->initialize(size, mDynamic);
}
- else
+
+ return mVertexBuffer->setBufferSize(size);
+}
+
+gl::ErrorOrResult<unsigned int> VertexBufferInterface::getSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances),
+ spaceRequired);
+
+ // Align to 16-byte boundary
+ unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u);
+
+ if (alignedSpaceRequired < spaceRequired)
{
- return mVertexBuffer->setBufferSize(size);
+ return gl::OutOfMemory()
+ << "Vertex buffer overflow in VertexBufferInterface::getSpaceRequired.";
}
+
+ return alignedSpaceRequired;
}
-unsigned int VertexBufferInterface::getWritePosition() const
+gl::Error VertexBufferInterface::discard()
{
- return mWritePosition;
+ return mVertexBuffer->discard();
}
-void VertexBufferInterface::setWritePosition(unsigned int writePosition)
+VertexBuffer *VertexBufferInterface::getVertexBuffer() const
{
- mWritePosition = writePosition;
+ return mVertexBuffer;
}
-gl::Error VertexBufferInterface::discard()
+// StreamingVertexBufferInterface Implementation
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory,
+ std::size_t initialSize)
+ : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0)
{
- return mVertexBuffer->discard();
+ // TODO(jmadill): Make an initialize method that can return an error.
+ ANGLE_SWALLOW_ERR(setBufferSize(static_cast<unsigned int>(initialSize)));
}
-gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib,
- GLenum currentValueType,
- GLint start,
- GLsizei count,
- GLsizei instances,
- unsigned int *outStreamOffset,
- const uint8_t *sourceData)
+StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
{
- gl::Error error(GL_NO_ERROR);
+}
- unsigned int spaceRequired;
- error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired);
- if (error.isError())
+gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
+{
+ unsigned int curBufferSize = getBufferSize();
+ if (size > curBufferSize)
+ {
+ ANGLE_TRY(setBufferSize(std::max(size, 3 * curBufferSize / 2)));
+ mWritePosition = 0;
+ }
+ else if (mWritePosition + size > curBufferSize)
{
- return error;
+ ANGLE_TRY(discard());
+ mWritePosition = 0;
}
- // Align to 16-byte boundary
- unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u);
+ return gl::NoError();
+}
+
+gl::Error StreamingVertexBufferInterface::storeDynamicAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData)
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired);
// Protect against integer overflow
- if (!IsUnsignedAdditionSafe(mWritePosition, alignedSpaceRequired) ||
- alignedSpaceRequired < spaceRequired)
+ angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
+ checkedPosition += spaceRequired;
+ if (!checkedPosition.IsValid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow.");
+ return gl::OutOfMemory()
+ << "Internal error, new vertex buffer write position would overflow.";
}
- error = reserveSpace(mReservedSpace);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(reserveSpace(mReservedSpace));
mReservedSpace = 0;
- error = mVertexBuffer->storeVertexAttributes(attrib, currentValueType, start, count, instances, mWritePosition, sourceData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, currentValueType, start, count,
+ instances, mWritePosition, sourceData));
if (outStreamOffset)
{
*outStreamOffset = mWritePosition;
}
- mWritePosition += alignedSpaceRequired;
+ mWritePosition += spaceRequired;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances)
+gl::Error StreamingVertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances)
{
- gl::Error error(GL_NO_ERROR);
-
- unsigned int requiredSpace;
- error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace);
- if (error.isError())
- {
- return error;
- }
+ unsigned int requiredSpace = 0;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances),
+ requiredSpace);
// Align to 16-byte boundary
- unsigned int alignedRequiredSpace = roundUp(requiredSpace, 16u);
+ auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
+ alignedRequiredSpace += mReservedSpace;
// Protect against integer overflow
- if (!IsUnsignedAdditionSafe(mReservedSpace, alignedRequiredSpace) ||
- alignedRequiredSpace < requiredSpace)
+ if (!alignedRequiredSpace.IsValid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Unable to reserve %u extra bytes in internal vertex buffer, "
- "it would result in an overflow.", requiredSpace);
+ return gl::OutOfMemory()
+ << "Unable to reserve " << requiredSpace
+ << " extra bytes in internal vertex buffer, it would result in an overflow.";
}
- mReservedSpace += alignedRequiredSpace;
+ mReservedSpace = alignedRequiredSpace.ValueOrDie();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-VertexBuffer* VertexBufferInterface::getVertexBuffer() const
+// StaticVertexBufferInterface Implementation
+StaticVertexBufferInterface::AttributeSignature::AttributeSignature()
+ : type(GL_NONE), size(0), stride(0), normalized(false), pureInteger(false), offset(0)
{
- return mVertexBuffer;
}
-bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib,
- GLenum currentValueType) const
+bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const
{
- gl::Buffer *buffer = attrib.buffer.get();
- BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
+ size_t attribStride = ComputeVertexAttributeStride(attrib, binding);
- if (!storage || !storage->supportsDirectBinding())
+ if (type != attrib.type || size != attrib.size || static_cast<GLuint>(stride) != attribStride ||
+ normalized != attrib.normalized || pureInteger != attrib.pureInteger)
{
return false;
}
- // Alignment restrictions: In D3D, vertex data must be aligned to
- // the format stride, or to a 4-byte boundary, whichever is smaller.
- // (Undocumented, and experimentally confirmed)
- size_t alignment = 4;
- bool requiresConversion = false;
-
- if (attrib.type != GL_FLOAT)
- {
- gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
-
- unsigned int outputElementSize;
- getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
- alignment = std::min<size_t>(outputElementSize, 4);
-
- // TODO(jmadill): add VertexFormatCaps
- requiresConversion = (mFactory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0;
- }
-
- bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
- (static_cast<size_t>(attrib.offset) % alignment == 0);
-
- return !requiresConversion && isAligned;
+ size_t attribOffset =
+ (static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % attribStride);
+ return (offset == attribOffset);
}
-StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize)
- : VertexBufferInterface(factory, true)
+void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
{
- setBufferSize(static_cast<unsigned int>(initialSize));
-}
-
-StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
-{
-}
-
-gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
-{
- unsigned int curBufferSize = getBufferSize();
- if (size > curBufferSize)
- {
- gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2));
- if (error.isError())
- {
- return error;
- }
- setWritePosition(0);
- }
- else if (getWritePosition() + size > curBufferSize)
- {
- gl::Error error = discard();
- if (error.isError())
- {
- return error;
- }
- setWritePosition(0);
- }
-
- return gl::Error(GL_NO_ERROR);
+ type = attrib.type;
+ size = attrib.size;
+ normalized = attrib.normalized;
+ pureInteger = attrib.pureInteger;
+ offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib, binding));
+ offset = static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) %
+ ComputeVertexAttributeStride(attrib, binding);
}
StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
- : VertexBufferInterface(factory, false), mIsCommitted(false)
+ : VertexBufferInterface(factory, false)
{
}
@@ -251,82 +258,36 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface()
{
}
-bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset)
+bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const
{
- for (unsigned int element = 0; element < mCache.size(); element++)
- {
- size_t attribStride = ComputeVertexAttributeStride(attrib);
-
- if (mCache[element].type == attrib.type && mCache[element].size == attrib.size &&
- mCache[element].stride == attribStride &&
- mCache[element].normalized == attrib.normalized &&
- mCache[element].pureInteger == attrib.pureInteger)
- {
- size_t offset = (static_cast<size_t>(attrib.offset) % attribStride);
- if (mCache[element].attributeOffset == offset)
- {
- if (outStreamOffset)
- {
- *outStreamOffset = mCache[element].streamOffset;
- }
- return true;
- }
- }
- }
-
- return false;
+ return mSignature.matchesAttribute(attrib, binding);
}
-gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size)
+void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
{
- unsigned int curSize = getBufferSize();
- if (curSize == 0)
- {
- return setBufferSize(size);
- }
- else if (curSize >= size)
- {
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized.");
- }
+ return mSignature.set(attrib, binding);
}
-gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib,
- GLenum currentValueType,
- GLint start,
- GLsizei count,
- GLsizei instances,
- unsigned int *outStreamOffset,
- const uint8_t *sourceData)
+gl::Error StaticVertexBufferInterface::storeStaticAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData)
{
- unsigned int streamOffset;
- gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValueType, start, count, instances, &streamOffset, sourceData);
- if (error.isError())
- {
- return error;
- }
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired);
+ ANGLE_TRY(setBufferSize(spaceRequired));
- size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib);
- VertexElement element = { attrib.type, attrib.size, static_cast<GLuint>(ComputeVertexAttributeStride(attrib)), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset };
- mCache.push_back(element);
-
- if (outStreamOffset)
- {
- *outStreamOffset = streamOffset;
- }
+ ASSERT(attrib.enabled);
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, GL_NONE, start, count,
+ instances, 0, sourceData));
- return gl::Error(GL_NO_ERROR);
+ mSignature.set(attrib, binding);
+ mVertexBuffer->hintUnmapResource();
+ return gl::NoError();
}
-void StaticVertexBufferInterface::commit()
-{
- if (getBufferSize() > 0)
- {
- mIsCommitted = true;
- }
-}
-}
+} // namespace rx