diff options
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp index ec85857264..7ff5171fca 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp @@ -26,12 +26,32 @@ namespace namespace rx { -static int elementsInBuffer(const gl::VertexAttribute &attribute, int size) +static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) { - int stride = attribute.stride(); + // Size cannot be larger than a GLsizei + if (size > static_cast<unsigned int>(std::numeric_limits<int>::max())) + { + size = static_cast<unsigned int>(std::numeric_limits<int>::max()); + } + + GLsizei stride = attribute.stride(); return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; } +static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount) +{ + // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. + // + // A vertex attribute with a positive divisor loads one instanced vertex for every set of + // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. + if (instanceDrawCount > 0 && attribute.mDivisor > 0) + { + return instanceDrawCount / attribute.mDivisor; + } + + return vertexDrawCount; +} + VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) { for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) @@ -92,7 +112,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 && + if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && !directStoragePossible(staticBuffer, attribs[i])) { buffer->invalidateStaticData(); @@ -116,12 +136,27 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], if (staticBuffer->getBufferSize() == 0) { int totalCount = elementsInBuffer(attribs[i], buffer->size()); - staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0); + if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) + { + return GL_OUT_OF_MEMORY; + } } } else { - mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances); + int totalCount = StreamingBufferElementCount(attribs[i], count, instances); + + // Undefined behaviour: + // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data. + if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount) + { + return GL_INVALID_OPERATION; + } + + if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances)) + { + return GL_OUT_OF_MEMORY; + } } } } @@ -149,7 +184,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], BufferStorage *storage = buffer ? buffer->getStorage() : NULL; bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); - std::size_t streamOffset = -1; + unsigned int streamOffset = 0; unsigned int outputElementSize = 0; if (directStorage) @@ -160,37 +195,40 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], } else if (staticBuffer) { - streamOffset = staticBuffer->lookupAttribute(attribs[i]); - outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0); + if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize)) + { + return GL_OUT_OF_MEMORY; + } - if (streamOffset == -1) + if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset)) { // Convert the entire buffer int totalCount = elementsInBuffer(attribs[i], storage->getSize()); int startIndex = attribs[i].mOffset / attribs[i].stride(); - streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0); + if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } } - if (streamOffset != -1) + unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; + unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0; + if (streamOffset + firstElementOffset + startOffset < streamOffset) { - streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; - - if (instances == 0 || attribs[i].mDivisor == 0) - { - streamOffset += start * outputElementSize; - } + return GL_OUT_OF_MEMORY; } + + streamOffset += firstElementOffset + startOffset; } else { - outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0); - streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances); - } - - if (streamOffset == -1) - { - return GL_OUT_OF_MEMORY; + int totalCount = StreamingBufferElementCount(attribs[i], count, instances); + if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || + !mStreamingBuffer->storeVertexAttributes(attribs[i], start, totalCount, instances, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } } translated[i].storage = directStorage ? storage : NULL; @@ -217,9 +255,13 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], mCurrentValue[i][3] != attribs[i].mCurrentValue[3]) { unsigned int requiredSpace = sizeof(float) * 4; - buffer->reserveRawDataSpace(requiredSpace); - int streamOffset = buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace); - if (streamOffset == -1) + if (!buffer->reserveRawDataSpace(requiredSpace)) + { + return GL_OUT_OF_MEMORY; + } + + unsigned int streamOffset; + if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset)) { return GL_OUT_OF_MEMORY; } |