diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp | 347 |
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 |