diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp | 374 |
1 files changed, 205 insertions, 169 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp index cb70b9e4ef..b392d0f4da 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -35,215 +35,217 @@ static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size size = static_cast<unsigned int>(std::numeric_limits<int>::max()); } - GLsizei stride = ComputeVertexAttributeStride(attrib); - return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; + GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib)); + return (size - attrib.offset % stride + + (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) / + stride; } -static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) +VertexDataManager::CurrentValueState::CurrentValueState() + : buffer(nullptr), + offset(0) { - // 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 && attrib.divisor > 0) - { - // When instanceDrawCount is not a multiple attrib.divisor, the division must round up. - // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced vertices. - return (instanceDrawCount + attrib.divisor - 1) / attrib.divisor; - } + data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN(); + data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN(); + data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN(); + data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN(); + data.Type = GL_FLOAT; +} - return vertexDrawCount; +VertexDataManager::CurrentValueState::~CurrentValueState() +{ + SafeDelete(buffer); } VertexDataManager::VertexDataManager(BufferFactoryD3D *factory) - : mFactory(factory) + : mFactory(factory), + mStreamingBuffer(nullptr), + // TODO(jmadill): use context caps + mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS) { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentValue[i].FloatValues[0] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i].FloatValues[1] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i].FloatValues[2] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i].FloatValues[3] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i].Type = GL_FLOAT; - mCurrentValueBuffer[i] = NULL; - mCurrentValueOffsets[i] = 0; - } - mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE); if (!mStreamingBuffer) { ERR("Failed to allocate the streaming vertex buffer."); } + + // TODO(jmadill): use context caps + mActiveEnabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); + mActiveDisabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); } VertexDataManager::~VertexDataManager() { - delete mStreamingBuffer; - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - delete mCurrentValueBuffer[i]; - } + SafeDelete(mStreamingBuffer); } void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes) { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); - for (size_t i = 0; i < vertexAttributes.size(); i++) + for (const TranslatedAttribute *translated : mActiveEnabledAttributes) { - const gl::VertexAttribute &attrib = vertexAttributes[i]; - if (attrib.enabled) + gl::Buffer *buffer = translated->attribute->buffer.get(); + BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; + StaticVertexBufferInterface *staticBuffer = + storage + ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE) + : nullptr; + + if (staticBuffer) { - gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + // Commit all the static vertex buffers. This fixes them in size/contents, and forces + // ANGLE to use a new static buffer (or recreate the static buffers) next time + staticBuffer->commit(); - if (staticBuffer) - { - staticBuffer->getVertexBuffer()->hintUnmapResource(); - } + staticBuffer->getVertexBuffer()->hintUnmapResource(); } } - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (auto ¤tValue : mCurrentValueCache) { - if (mCurrentValueBuffer[i] != NULL) + if (currentValue.buffer != nullptr) { - mCurrentValueBuffer[i]->getVertexBuffer()->hintUnmapResource(); + currentValue.buffer->getVertexBuffer()->hintUnmapResource(); } } } -gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, - TranslatedAttribute *translated, GLsizei instances) +gl::Error VertexDataManager::prepareVertexData(const gl::State &state, + GLint start, + GLsizei count, + std::vector<TranslatedAttribute> *translatedAttribs, + GLsizei instances) { if (!mStreamingBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } + // Compute active enabled and active disable attributes, for speed. + // TODO(jmadill): don't recompute if there was no state change const gl::VertexArray *vertexArray = state.getVertexArray(); - const std::vector<gl::VertexAttribute> &vertexAttributes = vertexArray->getVertexAttributes(); + const gl::Program *program = state.getProgram(); + const auto &vertexAttributes = vertexArray->getVertexAttributes(); + + mActiveEnabledAttributes.clear(); + mActiveDisabledAttributes.clear(); + translatedAttribs->clear(); - // Invalidate static buffers that don't contain matching attributes - for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { - translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1); - if (translated[attributeIndex].active && vertexAttributes[attributeIndex].enabled) + if (program->isAttribLocationActive(attribIndex)) { - invalidateMatchingStaticData(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex)); + // Resize automatically puts in empty attribs + translatedAttribs->resize(attribIndex + 1); + + TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; + + // Record the attribute now + translated->active = true; + translated->attribute = &vertexAttributes[attribIndex]; + translated->currentValueType = + state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type; + translated->divisor = vertexAttributes[attribIndex].divisor; + + if (vertexAttributes[attribIndex].enabled) + { + mActiveEnabledAttributes.push_back(translated); + + gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get(); + if (buffer) + { + // Also reinitialize static buffers which didn't contain matching data + // last time they were used + BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); + bufferImpl->reinitOutOfDateStaticData(); + } + } + else + { + mActiveDisabledAttributes.push_back(attribIndex); + } } } // Reserve the required space in the buffers - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { - if (translated[i].active && vertexAttributes[i].enabled) + gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances); + if (error.isError()) { - gl::Error error = reserveSpaceForAttrib(vertexAttributes[i], state.getVertexAttribCurrentValue(i), count, instances); - if (error.isError()) - { - return error; - } + return error; } } // Perform the vertex data translations - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { - const gl::VertexAttribute &curAttrib = vertexAttributes[i]; - if (translated[i].active) - { - if (curAttrib.enabled) - { - gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), - &translated[i], start, count, instances); + gl::Error error = storeAttribute(activeAttrib, start, count, instances); - if (error.isError()) - { - hintUnmapAllResources(vertexAttributes); - return error; - } - } - else - { - if (!mCurrentValueBuffer[i]) - { - mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); - } - - gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], - &mCurrentValue[i], &mCurrentValueOffsets[i], - mCurrentValueBuffer[i]); - if (error.isError()) - { - hintUnmapAllResources(vertexAttributes); - return error; - } - } + if (error.isError()) + { + hintUnmapAllResources(vertexAttributes); + return error; } } - // Hint to unmap all the resources - hintUnmapAllResources(vertexAttributes); - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (size_t attribIndex : mActiveDisabledAttributes) { - const gl::VertexAttribute &curAttrib = vertexAttributes[i]; - if (translated[i].active && curAttrib.enabled) + if (mCurrentValueCache[attribIndex].buffer == nullptr) { - gl::Buffer *buffer = curAttrib.buffer.get(); + mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); + } - if (buffer) - { - BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); - bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); - } + gl::Error error = storeCurrentValue( + state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)), + &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]); + if (error.isError()) + { + hintUnmapAllResources(vertexAttributes); + return error; } } - return gl::Error(GL_NO_ERROR); -} - -void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const -{ - gl::Buffer *buffer = attrib.buffer.get(); + // Hint to unmap all the resources + hintUnmapAllResources(vertexAttributes); - if (buffer) + for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { - BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); - StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); + gl::Buffer *buffer = activeAttrib->attribute->buffer.get(); - if (staticBuffer && - staticBuffer->getBufferSize() > 0 && - !staticBuffer->lookupAttribute(attrib, NULL) && - !staticBuffer->directStoragePossible(attrib, currentValue)) + if (buffer) { - bufferImpl->invalidateStaticData(); + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute); + bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize)); } } + + return gl::Error(GL_NO_ERROR); } -gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, +gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, GLsizei count, GLsizei instances) const { + const gl::VertexAttribute &attrib = *translatedAttrib.attribute; gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; + StaticVertexBufferInterface *staticBuffer = + bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY) + : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); - if (!vertexBuffer->directStoragePossible(attrib, currentValue)) + if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType)) { if (staticBuffer) { if (staticBuffer->getBufferSize() == 0) { - int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize()); + int totalCount = + ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())); gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0); if (error.isError()) { @@ -253,10 +255,13 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &at } else { - int totalCount = StreamingBufferElementCount(attrib, count, instances); - ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount); + size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); + ASSERT(!bufferImpl || + ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())) >= + static_cast<int>(totalCount)); - gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances); + gl::Error error = mStreamingBuffer->reserveVertexSpace( + attrib, static_cast<GLsizei>(totalCount), instances); if (error.isError()) { return error; @@ -267,33 +272,59 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &at return gl::Error(GL_NO_ERROR); } -gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, +gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated, GLint start, GLsizei count, GLsizei instances) { + const gl::VertexAttribute &attrib = *translated->attribute; + gl::Buffer *buffer = attrib.buffer.get(); ASSERT(buffer || attrib.pointer); + ASSERT(attrib.enabled); BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + StaticVertexBufferInterface *staticBuffer = + storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); - bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); - - unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; + bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType); // Instanced vertices do not apply the 'start' offset - GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start); + GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start); + + translated->vertexBuffer = vertexBuffer->getVertexBuffer(); if (directStorage) { - outputElementSize = ComputeVertexAttributeStride(attrib); - streamOffset = attrib.offset + outputElementSize * firstVertexIndex; + translated->storage = storage; + translated->serial = storage->getSerial(); + translated->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib)); + translated->offset = static_cast<unsigned int>(attrib.offset + translated->stride * firstVertexIndex); + + return gl::Error(GL_NO_ERROR); + } + + // Compute source data pointer + const uint8_t *sourceData = nullptr; + + if (buffer) + { + gl::Error error = storage->getData(&sourceData); + if (error.isError()) + { + return error; + } + sourceData += static_cast<int>(attrib.offset); + } + else + { + sourceData = static_cast<const uint8_t*>(attrib.pointer); } - else if (staticBuffer) + + unsigned int streamOffset = 0; + unsigned int outputElementSize = 0; + + if (staticBuffer) { gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); if (error.isError()) @@ -304,19 +335,30 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) { // Convert the entire buffer - int totalCount = ElementsInBuffer(attrib, storage->getSize()); - int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); - - error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, - 0, &streamOffset); + int totalCount = + ElementsInBuffer(attrib, static_cast<unsigned int>(storage->getSize())); + int startIndex = static_cast<int>(attrib.offset) / + static_cast<int>(ComputeVertexAttributeStride(attrib)); + + error = staticBuffer->storeVertexAttributes(attrib, + translated->currentValueType, + -startIndex, + totalCount, + 0, + &streamOffset, + sourceData); if (error.isError()) { return error; } } - unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; - unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0; + unsigned int firstElementOffset = + (static_cast<unsigned int>(attrib.offset) / + static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) * + outputElementSize; + ASSERT(attrib.divisor == 0 || firstVertexIndex == 0); + unsigned int startOffset = firstVertexIndex * outputElementSize; if (streamOffset + firstElementOffset + startOffset < streamOffset) { return gl::Error(GL_OUT_OF_MEMORY); @@ -326,69 +368,63 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, } else { - int totalCount = StreamingBufferElementCount(attrib, count, instances); + size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); if (error.isError()) { return error; } - error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, firstVertexIndex, - totalCount, instances, &streamOffset); + error = mStreamingBuffer->storeVertexAttributes( + attrib, translated->currentValueType, firstVertexIndex, + static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData); if (error.isError()) { return error; } } - translated->storage = directStorage ? storage : NULL; - translated->vertexBuffer = vertexBuffer->getVertexBuffer(); - translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); - translated->divisor = attrib.divisor; - - translated->attribute = &attrib; - translated->currentValueType = currentValue.Type; + translated->storage = nullptr; + translated->serial = vertexBuffer->getSerial(); translated->stride = outputElementSize; translated->offset = streamOffset; return gl::Error(GL_NO_ERROR); } -gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, +gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, TranslatedAttribute *translated, - gl::VertexAttribCurrentValueData *cachedValue, - size_t *cachedOffset, - StreamingVertexBufferInterface *buffer) + CurrentValueState *cachedState) { - if (*cachedValue != currentValue) + if (cachedState->data != currentValue) { - gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0); + const gl::VertexAttribute &attrib = *translated->attribute; + + gl::Error error = cachedState->buffer->reserveVertexSpace(attrib, 1, 0); if (error.isError()) { return error; } + const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues); unsigned int streamOffset; - error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset); + error = cachedState->buffer->storeVertexAttributes(attrib, currentValue.Type, 0, 1, 0, &streamOffset, sourceData); if (error.isError()) { return error; } - *cachedValue = currentValue; - *cachedOffset = streamOffset; + cachedState->data = currentValue; + cachedState->offset = streamOffset; } translated->storage = NULL; - translated->vertexBuffer = buffer->getVertexBuffer(); - translated->serial = buffer->getSerial(); + translated->vertexBuffer = cachedState->buffer->getVertexBuffer(); + translated->serial = cachedState->buffer->getSerial(); translated->divisor = 0; - translated->attribute = &attrib; - translated->currentValueType = currentValue.Type; translated->stride = 0; - translated->offset = *cachedOffset; + translated->offset = static_cast<unsigned int>(cachedState->offset); return gl::Error(GL_NO_ERROR); } |