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
parent 442b7deb
...@@ -22,15 +22,10 @@ namespace gl ...@@ -22,15 +22,10 @@ namespace gl
{ {
Buffer::Buffer(BufferBackEnd *backEnd) Buffer::Buffer(BufferBackEnd *backEnd)
: mBackEnd(backEnd), mIdentityTranslation(NULL) : mBackEnd(backEnd)
{ {
} }
Buffer::~Buffer()
{
delete mIdentityTranslation;
}
GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage) GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage)
{ {
if (size < 0) return GL_INVALID_VALUE; if (size < 0) return GL_INVALID_VALUE;
...@@ -40,14 +35,10 @@ GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage) ...@@ -40,14 +35,10 @@ GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage)
if (size == 0) if (size == 0)
{ {
mContents.clear(); mContents.clear();
delete mIdentityTranslation;
mIdentityTranslation = NULL;
} }
else if (size != mContents.size()) else if (size != mContents.size())
{ {
// vector::resize only provides the basic exception guarantee, so use temporaries & swap to get the strong exception guarantee. // vector::resize only provides the basic exception guarantee, so use temporaries & swap to get the strong exception guarantee.
// We don't want to risk having mContents and mIdentityTranslation that have different contents or even different sizes.
std::vector<GLubyte> newContents; std::vector<GLubyte> newContents;
if (newdata != NULL) if (newdata != NULL)
...@@ -59,14 +50,10 @@ GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage) ...@@ -59,14 +50,10 @@ GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage)
newContents.assign(size, 0); newContents.assign(size, 0);
} }
TranslatedVertexBuffer *newIdentityTranslation = mBackEnd->createVertexBuffer(size);
// No exceptions allowed after this point. // No exceptions allowed after this point.
mContents.swap(newContents); mContents.swap(newContents);
delete mIdentityTranslation;
mIdentityTranslation = newIdentityTranslation;
} }
else if (newdata != NULL) else if (newdata != NULL)
{ {
...@@ -75,7 +62,7 @@ GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage) ...@@ -75,7 +62,7 @@ GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage)
mUsage = usage; mUsage = usage;
return copyToIdentityBuffer(0, size); return GL_NO_ERROR;
} }
GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset) GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset)
...@@ -87,22 +74,6 @@ GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset) ...@@ -87,22 +74,6 @@ GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset)
const GLubyte *newdata = static_cast<const GLubyte*>(data); const GLubyte *newdata = static_cast<const GLubyte*>(data);
copy(newdata, newdata + size, mContents.begin() + offset); copy(newdata, newdata + size, mContents.begin() + offset);
return copyToIdentityBuffer(offset, size);
}
GLenum Buffer::copyToIdentityBuffer(GLintptr offset, GLsizeiptr length)
{
ASSERT(offset >= 0 && length >= 0);
if (length > 0) // If length == 0 mIdentityTranslation might be NULL.
{
// This is a stalling map. Not great for performance.
GLubyte *p = static_cast<GLubyte*>(mIdentityTranslation->map());
memcpy(p + offset, &mContents[0] + offset, length);
mIdentityTranslation->unmap();
}
return GL_NO_ERROR; return GL_NO_ERROR;
} }
......
...@@ -29,7 +29,6 @@ class Buffer ...@@ -29,7 +29,6 @@ class Buffer
{ {
public: public:
explicit Buffer(BufferBackEnd *backEnd); explicit Buffer(BufferBackEnd *backEnd);
~Buffer();
GLenum bufferData(const void *data, GLsizeiptr size, GLenum usage); GLenum bufferData(const void *data, GLsizeiptr size, GLenum usage);
GLenum bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); GLenum bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
...@@ -38,8 +37,6 @@ class Buffer ...@@ -38,8 +37,6 @@ class Buffer
GLsizeiptr size() const { return mContents.size(); } GLsizeiptr size() const { return mContents.size(); }
GLenum usage() const { return mUsage; } GLenum usage() const { return mUsage; }
TranslatedVertexBuffer *identityBuffer() { return mIdentityTranslation; }
private: private:
DISALLOW_COPY_AND_ASSIGN(Buffer); DISALLOW_COPY_AND_ASSIGN(Buffer);
...@@ -47,9 +44,6 @@ class Buffer ...@@ -47,9 +44,6 @@ class Buffer
GLenum mUsage; GLenum mUsage;
BufferBackEnd *mBackEnd; BufferBackEnd *mBackEnd;
TranslatedVertexBuffer *mIdentityTranslation;
GLenum copyToIdentityBuffer(GLintptr offset, GLsizeiptr length);
}; };
} }
......
...@@ -66,8 +66,6 @@ GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count, ...@@ -66,8 +66,6 @@ GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
const AttributeState *attribs = mContext->getVertexAttribBlock(); const AttributeState *attribs = mContext->getVertexAttribBlock();
const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs(); const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
std::bitset<MAX_VERTEX_ATTRIBS> translateOrLift;
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{ {
if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer)) if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer))
...@@ -81,96 +79,69 @@ GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count, ...@@ -81,96 +79,69 @@ GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
processNonArrayAttributes(attribs, activeAttribs, translated); 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++) for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{ {
if (activeAttribs[i] && attribs[i].mEnabled) if (activeAttribs[i] && attribs[i].mEnabled)
{ {
if (attribs[i].mBoundBuffer != 0 && mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized).identity) requiredSpace += spaceRequired(attribs[i], count);
{
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;
}
} }
} }
// Handle any attributes needing translation or lifting. if (requiredSpace > mStreamBuffer->size())
if (translateOrLift.any())
{ {
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++)
{
if (translateOrLift[i])
{
requiredSpace += spaceRequired(attribs[i], count);
}
}
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); TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
delete mStreamBuffer; delete mStreamBuffer;
mStreamBuffer = newStreamBuffer; mStreamBuffer = newStreamBuffer;
} }
mStreamBuffer->reserveSpace(requiredSpace); mStreamBuffer->reserveSpace(requiredSpace);
for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++) 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);
{
FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
translated[i].type = attribs[i].mType; translated[i].type = attribs[i].mType;
translated[i].size = attribs[i].mSize; translated[i].size = attribs[i].mSize;
translated[i].normalized = attribs[i].mNormalized; translated[i].normalized = attribs[i].mNormalized;
translated[i].stride = formatConverter.outputVertexSize; translated[i].stride = formatConverter.outputVertexSize;
translated[i].buffer = mStreamBuffer; translated[i].buffer = mStreamBuffer;
void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset); void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
const void *input; const void *input;
if (attribs[i].mBoundBuffer) if (attribs[i].mBoundBuffer)
{ {
input = mContext->getBuffer(attribs[i].mBoundBuffer)->data(); input = mContext->getBuffer(attribs[i].mBoundBuffer)->data();
input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer); input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer);
} }
else else
{ {
input = attribs[i].mPointer; input = attribs[i].mPointer;
} }
size_t inputStride = interpretGlStride(attribs[i]); size_t inputStride = interpretGlStride(attribs[i]);
input = static_cast<const char*>(input) + inputStride * start; 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); formatConverter.convertArray(input, inputStride, count, output);
mStreamBuffer->unmap();
} }
mStreamBuffer->unmap();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment