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 MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 615
#define BUILD_REVISION 616
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -23,15 +23,16 @@ Buffer::Buffer(GLuint id) : RefCountObject(id)
mSize = 0;
mUsage = GL_DYNAMIC_DRAW;
mVertexBuffer = NULL;
mIndexBuffer = NULL;
mStaticVertexBuffer = NULL;
mStaticIndexBuffer = NULL;
mUnmodifiedDataUse = 0;
}
Buffer::~Buffer()
{
delete[] mContents;
delete mVertexBuffer;
delete mIndexBuffer;
delete mStaticVertexBuffer;
delete mStaticIndexBuffer;
}
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
......@@ -60,47 +61,55 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
if (usage == GL_STATIC_DRAW)
{
mVertexBuffer = new StaticVertexBuffer(getDevice());
mIndexBuffer = new StaticIndexBuffer(getDevice());
mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
memcpy(mContents + offset, data, size);
if ((mVertexBuffer && mVertexBuffer->size() != 0) || (mIndexBuffer && mIndexBuffer->size() != 0))
if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
{
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()
{
delete mVertexBuffer;
mVertexBuffer = NULL;
delete mStaticVertexBuffer;
mStaticVertexBuffer = NULL;
delete mStaticIndexBuffer;
mStaticIndexBuffer = NULL;
mUnmodifiedDataUse = 0;
}
delete mIndexBuffer;
mIndexBuffer = NULL;
// Creates static buffers if sufficient used data has been left unmodified
void Buffer::promoteStaticUsage(int dataSize)
{
if (!mStaticVertexBuffer && !mStaticIndexBuffer)
{
mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * mSize)
{
mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
}
}
......@@ -39,9 +39,10 @@ class Buffer : public RefCountObject
size_t size() const { return mSize; }
GLenum usage() const { return mUsage; }
StaticVertexBuffer *getVertexBuffer();
StaticIndexBuffer *getIndexBuffer();
StaticVertexBuffer *getStaticVertexBuffer();
StaticIndexBuffer *getStaticIndexBuffer();
void invalidateStaticData();
void promoteStaticUsage(int dataSize);
private:
DISALLOW_COPY_AND_ASSIGN(Buffer);
......@@ -50,8 +51,9 @@ class Buffer : public RefCountObject
size_t mSize;
GLenum mUsage;
StaticVertexBuffer *mVertexBuffer;
StaticIndexBuffer *mIndexBuffer;
StaticVertexBuffer *mStaticVertexBuffer;
StaticIndexBuffer *mStaticIndexBuffer;
size_t mUnmodifiedDataUse;
};
}
......
......@@ -139,7 +139,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *bu
StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
StaticIndexBuffer *staticBuffer = buffer ? buffer->getIndexBuffer() : NULL;
StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
IndexBuffer *indexBuffer = streamingBuffer;
UINT streamOffset = 0;
......@@ -202,6 +202,11 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *bu
translated->indexBuffer = indexBuffer->getBuffer();
translated->startIndex = streamOffset / indexSize(format);
if (buffer)
{
buffer->promoteStaticUsage(count * typeSize(type));
}
return GL_NO_ERROR;
}
......
......@@ -127,7 +127,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
if (translated[i].active && attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
StaticVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL;
StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
if (staticBuffer)
{
......@@ -158,7 +158,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
if (translated[i].active && attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
ArrayVertexBuffer *staticBuffer = buffer ? buffer->getVertexBuffer() : NULL;
ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer;
if (vertexBuffer)
......@@ -173,10 +173,10 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
{
if (translated[i].active)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
if (attribs[i].mArrayEnabled)
{
Buffer *buffer = attribs[i].mBoundBuffer.get();
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
......@@ -186,7 +186,7 @@ GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, Translat
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);
UINT streamOffset = -1;
......@@ -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;
}
......
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