Improve TranslatedVertexBuffer::map performance
TRAC #11392
- Don't use the identity translation buffer, but always copy into a streaming buffer.
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch
Author: Andrew Lewycky
git-svn-id: https://angleproject.googlecode.com/svn/trunk@264 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/geometry/VertexDataManager.cpp b/src/libGLESv2/geometry/VertexDataManager.cpp
index 42a051e..25e63a8 100644
--- a/src/libGLESv2/geometry/VertexDataManager.cpp
+++ b/src/libGLESv2/geometry/VertexDataManager.cpp
@@ -66,8 +66,6 @@
const AttributeState *attribs = mContext->getVertexAttribBlock();
const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
- std::bitset<MAX_VERTEX_ATTRIBS> translateOrLift;
-
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer))
@@ -81,96 +79,69 @@
processNonArrayAttributes(attribs, activeAttribs, translated);
- // Handle the identity-mapped attributes.
+ // Process array attributes.
+
+ std::size_t requiredSpace = 0;
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (activeAttribs[i] && attribs[i].mEnabled)
{
- if (attribs[i].mBoundBuffer != 0 && mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized).identity)
- {
- std::size_t stride = interpretGlStride(attribs[i]);
- std::size_t offset = static_cast<std::size_t>(static_cast<const char*>(attribs[i].mPointer) - static_cast<const char*>(NULL)) + stride * start;
-
- if (mBackend->validateStream(attribs[i].mType, attribs[i].mSize, stride, offset))
- {
- translated[i].type = attribs[i].mType;
- translated[i].size = attribs[i].mSize;
- translated[i].normalized = attribs[i].mNormalized;
- translated[i].stride = stride;
- translated[i].offset = offset;
- translated[i].buffer = mContext->getBuffer(attribs[i].mBoundBuffer)->identityBuffer();
- }
- else
- {
- translateOrLift[i] = true;
- }
- }
- else
- {
- translateOrLift[i] = true;
- }
+ requiredSpace += spaceRequired(attribs[i], count);
}
}
- // Handle any attributes needing translation or lifting.
- if (translateOrLift.any())
+ if (requiredSpace > mStreamBuffer->size())
{
- std::size_t requiredSpace = 0;
+ std::size_t newSize = std::max(requiredSpace, 3 * mStreamBuffer->size() / 2); // 1.5 x mStreamBuffer->size() is arbitrary and should be checked to see we don't have too many reallocations.
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
+
+ delete mStreamBuffer;
+ mStreamBuffer = newStreamBuffer;
+ }
+
+ mStreamBuffer->reserveSpace(requiredSpace);
+
+ for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (activeAttribs[i] && attribs[i].mEnabled)
{
- if (translateOrLift[i])
+ FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
+
+ translated[i].type = attribs[i].mType;
+ translated[i].size = attribs[i].mSize;
+ translated[i].normalized = attribs[i].mNormalized;
+ translated[i].stride = formatConverter.outputVertexSize;
+ translated[i].buffer = mStreamBuffer;
+
+ void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
+
+ const void *input;
+ if (attribs[i].mBoundBuffer)
{
- requiredSpace += spaceRequired(attribs[i], count);
+ input = mContext->getBuffer(attribs[i].mBoundBuffer)->data();
+ input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer);
}
- }
-
- if (requiredSpace > mStreamBuffer->size())
- {
- std::size_t newSize = std::max(requiredSpace, 3 * mStreamBuffer->size() / 2); // 1.5 x mStreamBuffer->size() is arbitrary and should be checked to see we don't have too many reallocations.
-
- TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
-
- delete mStreamBuffer;
- mStreamBuffer = newStreamBuffer;
- }
-
- mStreamBuffer->reserveSpace(requiredSpace);
-
- for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- if (translateOrLift[i])
+ else
{
- FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
+ input = attribs[i].mPointer;
+ }
- translated[i].type = attribs[i].mType;
- translated[i].size = attribs[i].mSize;
- translated[i].normalized = attribs[i].mNormalized;
- translated[i].stride = formatConverter.outputVertexSize;
- translated[i].buffer = mStreamBuffer;
+ size_t inputStride = interpretGlStride(attribs[i]);
- void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
+ input = static_cast<const char*>(input) + inputStride * start;
- const void *input;
- if (attribs[i].mBoundBuffer)
- {
- input = mContext->getBuffer(attribs[i].mBoundBuffer)->data();
- input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer);
- }
- else
- {
- input = attribs[i].mPointer;
- }
-
- size_t inputStride = interpretGlStride(attribs[i]);
-
- input = static_cast<const char*>(input) + inputStride * start;
-
+ if (formatConverter.identity && inputStride == typeSize(attribs[i].mType) * attribs[i].mSize)
+ {
+ memcpy(output, input, count * inputStride);
+ }
+ else
+ {
formatConverter.convertArray(input, inputStride, count, output);
-
- mStreamBuffer->unmap();
}
+
+ mStreamBuffer->unmap();
}
}