Heuristically optimize buffer usage.

TRAC #16343 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@616 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 733ba93b
#define MAJOR_VERSION 0 #define MAJOR_VERSION 0
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 615 #define BUILD_REVISION 616
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -23,15 +23,16 @@ Buffer::Buffer(GLuint id) : RefCountObject(id) ...@@ -23,15 +23,16 @@ Buffer::Buffer(GLuint id) : RefCountObject(id)
mSize = 0; mSize = 0;
mUsage = GL_DYNAMIC_DRAW; mUsage = GL_DYNAMIC_DRAW;
mVertexBuffer = NULL; mStaticVertexBuffer = NULL;
mIndexBuffer = NULL; mStaticIndexBuffer = NULL;
mUnmodifiedDataUse = 0;
} }
Buffer::~Buffer() Buffer::~Buffer()
{ {
delete[] mContents; delete[] mContents;
delete mVertexBuffer; delete mStaticVertexBuffer;
delete mIndexBuffer; delete mStaticIndexBuffer;
} }
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
...@@ -60,8 +61,8 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) ...@@ -60,8 +61,8 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
if (usage == GL_STATIC_DRAW) if (usage == GL_STATIC_DRAW)
{ {
mVertexBuffer = new StaticVertexBuffer(getDevice()); mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
mIndexBuffer = new StaticIndexBuffer(getDevice()); mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
} }
} }
...@@ -69,38 +70,46 @@ void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) ...@@ -69,38 +70,46 @@ void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{ {
memcpy(mContents + offset, data, size); memcpy(mContents + offset, data, size);
if ((mVertexBuffer && mVertexBuffer->size() != 0) || (mIndexBuffer && mIndexBuffer->size() != 0)) if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
{ {
invalidateStaticData(); invalidateStaticData();
if (mUsage == GL_STATIC_DRAW)
{
// If applications update the buffer data after it has already been used in a draw call,
// it most likely isn't used as a static buffer so we should fall back to streaming usage
// for best performance. So ignore the usage hint and don't create new static buffers.
// mVertexBuffer = new StaticVertexBuffer(getDevice());
// mIndexBuffer = new StaticIndexBuffer(getDevice());
}
} }
} }
StaticVertexBuffer *Buffer::getVertexBuffer() StaticVertexBuffer *Buffer::getStaticVertexBuffer()
{ {
return mVertexBuffer; return mStaticVertexBuffer;
} }
StaticIndexBuffer *Buffer::getIndexBuffer() StaticIndexBuffer *Buffer::getStaticIndexBuffer()
{ {
return mIndexBuffer; return mStaticIndexBuffer;
} }
void Buffer::invalidateStaticData() void Buffer::invalidateStaticData()
{ {
delete mVertexBuffer; delete mStaticVertexBuffer;
mVertexBuffer = NULL; mStaticVertexBuffer = NULL;
delete mStaticIndexBuffer;
mStaticIndexBuffer = NULL;
mUnmodifiedDataUse = 0;
}
// Creates static buffers if sufficient used data has been left unmodified
void Buffer::promoteStaticUsage(int dataSize)
{
if (!mStaticVertexBuffer && !mStaticIndexBuffer)
{
mUnmodifiedDataUse += dataSize;
delete mIndexBuffer; if (mUnmodifiedDataUse > 3 * mSize)
mIndexBuffer = NULL; {
mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
} }
} }
...@@ -39,9 +39,10 @@ class Buffer : public RefCountObject ...@@ -39,9 +39,10 @@ class Buffer : public RefCountObject
size_t size() const { return mSize; } size_t size() const { return mSize; }
GLenum usage() const { return mUsage; } GLenum usage() const { return mUsage; }
StaticVertexBuffer *getVertexBuffer(); StaticVertexBuffer *getStaticVertexBuffer();
StaticIndexBuffer *getIndexBuffer(); StaticIndexBuffer *getStaticIndexBuffer();
void invalidateStaticData(); void invalidateStaticData();
void promoteStaticUsage(int dataSize);
private: private:
DISALLOW_COPY_AND_ASSIGN(Buffer); DISALLOW_COPY_AND_ASSIGN(Buffer);
...@@ -50,8 +51,9 @@ class Buffer : public RefCountObject ...@@ -50,8 +51,9 @@ class Buffer : public RefCountObject
size_t mSize; size_t mSize;
GLenum mUsage; GLenum mUsage;
StaticVertexBuffer *mVertexBuffer; StaticVertexBuffer *mStaticVertexBuffer;
StaticIndexBuffer *mIndexBuffer; StaticIndexBuffer *mStaticIndexBuffer;
size_t mUnmodifiedDataUse;
}; };
} }
......
...@@ -139,7 +139,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *bu ...@@ -139,7 +139,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *bu
StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
StaticIndexBuffer *staticBuffer = buffer ? buffer->getIndexBuffer() : NULL; StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
IndexBuffer *indexBuffer = streamingBuffer; IndexBuffer *indexBuffer = streamingBuffer;
UINT streamOffset = 0; UINT streamOffset = 0;
...@@ -202,6 +202,11 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *bu ...@@ -202,6 +202,11 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *bu
translated->indexBuffer = indexBuffer->getBuffer(); translated->indexBuffer = indexBuffer->getBuffer();
translated->startIndex = streamOffset / indexSize(format); translated->startIndex = streamOffset / indexSize(format);
if (buffer)
{
buffer->promoteStaticUsage(count * typeSize(type));
}
return GL_NO_ERROR; return GL_NO_ERROR;
} }
......
...@@ -127,7 +127,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -127,7 +127,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
if (translated[i].active && attribs[i].mArrayEnabled) if (translated[i].active && attribs[i].mArrayEnabled)
{ {
Buffer *buffer = attribs[i].mBoundBuffer.get(); Buffer *buffer = attribs[i].mBoundBuffer.get();
StaticVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
if (staticBuffer) if (staticBuffer)
{ {
...@@ -158,7 +158,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -158,7 +158,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
if (translated[i].active && attribs[i].mArrayEnabled) if (translated[i].active && attribs[i].mArrayEnabled)
{ {
Buffer *buffer = attribs[i].mBoundBuffer.get(); Buffer *buffer = attribs[i].mBoundBuffer.get();
ArrayVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer; ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer;
if (vertexBuffer) if (vertexBuffer)
...@@ -173,10 +173,10 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -173,10 +173,10 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
{ {
if (translated[i].active) if (translated[i].active)
{ {
Buffer *buffer = attribs[i].mBoundBuffer.get();
if (attribs[i].mArrayEnabled) if (attribs[i].mArrayEnabled)
{ {
Buffer *buffer = attribs[i].mBoundBuffer.get();
if (!buffer && attribs[i].mPointer == NULL) if (!buffer && attribs[i].mPointer == NULL)
{ {
// This is an application error that would normally result in a crash, but we catch it and return an error // This is an application error that would normally result in a crash, but we catch it and return an error
...@@ -186,7 +186,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -186,7 +186,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
const FormatConverter &converter = formatConverter(attribs[i]); const FormatConverter &converter = formatConverter(attribs[i]);
StaticVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL; StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer); ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer);
UINT streamOffset = -1; UINT streamOffset = -1;
...@@ -242,6 +242,19 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat ...@@ -242,6 +242,19 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
} }
} }
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
if (translated[i].active && attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
if (buffer)
{
buffer->promoteStaticUsage(count * attribs[i].typeSize());
}
}
}
return GL_NO_ERROR; return GL_NO_ERROR;
} }
......
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