summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2012-05-15 16:42:04 -0500
committerDave Parks <davep@lindenlab.com>2012-05-15 16:42:04 -0500
commit89b0b6ac7198653d989dea78ee1c3d3f4f61161f (patch)
tree03184fb7c5723a766182a2fcfa0b86340e3761e1 /indra/llrender
parentf1f9b1c3b73b245fef3c976a9a1d71009bdbf3e0 (diff)
MAINT-616 Different VBO Pooling scheme -- populate VBO pool with buffers that are likely to be requested, but never reuse a previously used buffer.
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llvertexbuffer.cpp79
-rw-r--r--indra/llrender/llvertexbuffer.h16
2 files changed, 85 insertions, 10 deletions
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 1b179bdbb1..7b12304967 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -38,7 +38,7 @@
#include "llglslshader.h"
#include "llmemory.h"
-#define LL_VBO_POOLING 0
+#define LL_VBO_POOLING 1
//Next Highest Power Of Two
//helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
@@ -67,6 +67,7 @@ U32 wpo2(U32 i)
const U32 LL_VBO_BLOCK_SIZE = 2048;
+const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024;
U32 vbo_block_size(U32 size)
{ //what block size will fit size?
@@ -79,6 +80,7 @@ U32 vbo_block_index(U32 size)
return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;
}
+const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
//============================================================================
@@ -169,8 +171,15 @@ public:
};
+LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType)
+: mUsage(vboUsage), mType(vboType)
+{
+ mMissCount.resize(LL_VBO_POOL_SEED_COUNT);
+ std::fill(mMissCount.begin(), mMissCount.end(), 0);
+}
+
-volatile U8* LLVBOPool::allocate(U32& name, U32 size)
+volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
{
llassert(vbo_block_size(size) == size);
@@ -183,14 +192,20 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
if (mFreeList.size() <= i)
{
mFreeList.resize(i+1);
+ mMissCount.resize(i+1);
}
- if (mFreeList[i].empty())
+ if (mFreeList[i].empty() || for_seed)
{
//make a new buffer
glGenBuffersARB(1, &name);
glBindBufferARB(mType, name);
+ if (!for_seed && i < LL_VBO_POOL_SEED_COUNT)
+ { //record this miss
+ mMissCount[i]++;
+ }
+
if (mType == GL_ARRAY_BUFFER_ARB)
{
LLVertexBuffer::sAllocatedBytes += size;
@@ -211,6 +226,25 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
}
glBindBufferARB(mType, 0);
+
+ if (for_seed)
+ { //put into pool for future use
+ llassert(mFreeList.size() > i);
+
+ Record rec;
+ rec.mGLName = name;
+ rec.mClientData = ret;
+
+ if (mType == GL_ARRAY_BUFFER_ARB)
+ {
+ sBytesPooled += size;
+ }
+ else
+ {
+ sIndexBytesPooled += size;
+ }
+ mFreeList[i].push_back(rec);
+ }
}
else
{
@@ -263,7 +297,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
{
llassert(vbo_block_size(size) == size);
-#if LL_VBO_POOLING
+#if 0 && LL_VBO_POOLING
U32 i = vbo_block_index(size);
@@ -304,6 +338,31 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
#endif
}
+void LLVBOPool::seedPool()
+{
+ U32 dummy_name = 0;
+
+ if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)
+ {
+ mFreeList.resize(LL_VBO_POOL_SEED_COUNT);
+ }
+
+ for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)
+ {
+ if (mMissCount[i] > mFreeList[i].size())
+ {
+ U32 size = i*LL_VBO_BLOCK_SIZE;
+
+ S32 count = mMissCount[i] - mFreeList[i].size();
+ for (U32 j = 0; j < count; ++j)
+ {
+ allocate(dummy_name, size, true);
+ }
+ }
+ }
+}
+
+
void LLVBOPool::cleanup()
{
U32 size = 1;
@@ -339,6 +398,9 @@ void LLVBOPool::cleanup()
size *= 2;
}
+
+ //reset miss counts
+ std::fill(mMissCount.begin(), mMissCount.end(), 0);
}
@@ -374,6 +436,15 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
//static
+void LLVertexBuffer::seedPools()
+{
+ sStreamVBOPool.seedPool();
+ sDynamicVBOPool.seedPool();
+ sStreamIBOPool.seedPool();
+ sDynamicIBOPool.seedPool();
+}
+
+//static
void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
if (sLastMask != data_mask)
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 7477dec3ad..a64daa1a90 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -57,20 +57,20 @@ public:
static U32 sBytesPooled;
static U32 sIndexBytesPooled;
- LLVBOPool(U32 vboUsage, U32 vboType)
- : mUsage(vboUsage)
- , mType(vboType)
- {}
-
+ LLVBOPool(U32 vboUsage, U32 vboType);
+
const U32 mUsage;
const U32 mType;
//size MUST be a power of 2
- volatile U8* allocate(U32& name, U32 size);
+ volatile U8* allocate(U32& name, U32 size, bool for_seed = false);
//size MUST be the size provided to allocate that returned the given name
void release(U32 name, volatile U8* buffer, U32 size);
+ //batch allocate buffers to be provided to the application on demand
+ void seedPool();
+
//destroy all records in mFreeList
void cleanup();
@@ -83,6 +83,8 @@ public:
typedef std::list<Record> record_list_t;
std::vector<record_list_t> mFreeList;
+ std::vector<U32> mMissCount;
+
};
class LLGLFence
@@ -129,6 +131,8 @@ public:
static bool sUseVAO;
static bool sPreferStreamDraw;
+ static void seedPools();
+
static void initClass(bool use_vbo, bool no_vbo_mapping);
static void cleanupClass();
static void setupClientArrays(U32 data_mask);