summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2011-10-13 01:19:45 -0500
committerDave Parks <davep@lindenlab.com>2011-10-13 01:19:45 -0500
commit7b6723d1e0158d5dc326266a0332e87f634f9755 (patch)
tree10efed7ccda1a80889bfb65cd64c86b8d33c75ed
parent1a499c13c813d4aa9631ffae00b36a053f260747 (diff)
SH-1650 Mitigate memory fragmentation by holding onto and reusing VBOs
-rw-r--r--indra/llrender/llvertexbuffer.cpp458
-rw-r--r--indra/llrender/llvertexbuffer.h69
-rw-r--r--indra/newview/lldrawpoolavatar.cpp6
-rw-r--r--indra/newview/lldrawpooltree.cpp4
-rw-r--r--indra/newview/llface.cpp13
-rw-r--r--indra/newview/llfloatermodelpreview.cpp2
-rw-r--r--indra/newview/llspatialpartition.cpp10
-rw-r--r--indra/newview/llviewerdisplay.cpp4
-rw-r--r--indra/newview/llviewerwindow.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp4
-rw-r--r--indra/newview/llvowlsky.cpp4
-rw-r--r--indra/newview/pipeline.cpp26
12 files changed, 257 insertions, 345 deletions
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 4484a880cc..ad99bd1807 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -38,6 +38,17 @@
#include "llglslshader.h"
#include "llmemory.h"
+//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
+U32 nhpo2(U32 v)
+{
+ U32 r = 1;
+ while (r < v) {
+ r *= 2;
+ }
+ return r;
+}
+
//============================================================================
@@ -46,6 +57,7 @@ LLVBOPool LLVertexBuffer::sStreamVBOPool;
LLVBOPool LLVertexBuffer::sDynamicVBOPool;
LLVBOPool LLVertexBuffer::sStreamIBOPool;
LLVBOPool LLVertexBuffer::sDynamicIBOPool;
+U32 LLVBOPool::sBytesPooled = 0;
LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
U32 LLVertexBuffer::sBindCount = 0;
@@ -66,7 +78,6 @@ BOOL LLVertexBuffer::sMapped = FALSE;
BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
BOOL LLVertexBuffer::sUseVAO = FALSE;
BOOL LLVertexBuffer::sPreferStreamDraw = FALSE;
-std::vector<U32> LLVertexBuffer::sDeleteList;
const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms
@@ -122,6 +133,107 @@ public:
};
+
+//which power of 2 is i?
+//assumes i is a power of 2 > 0
+U32 wpo2(U32 i)
+{
+ llassert(i > 0);
+ llassert(nhpo2(i) == i);
+
+ U32 r = 0;
+
+ while (i >>= 1) ++r;
+
+ return r;
+}
+
+U8* LLVBOPool::allocate(U32& name, U32 size)
+{
+ llassert(nhpo2(size) == size);
+
+ U32 i = wpo2(size);
+
+ if (mFreeList.size() <= i)
+ {
+ mFreeList.resize(i+1);
+ }
+
+ U8* ret = NULL;
+
+ if (mFreeList[i].empty())
+ {
+ //make a new buffer
+ glGenBuffersARB(1, &name);
+ glBindBufferARB(mType, name);
+ glBufferDataARB(mType, size, 0, mUsage);
+ LLVertexBuffer::sAllocatedBytes += size;
+
+ if (LLVertexBuffer::sDisableVBOMapping)
+ {
+ ret = (U8*) ll_aligned_malloc_16(size);
+ }
+ glBindBufferARB(mType, 0);
+ }
+ else
+ {
+ name = mFreeList[i].front().mGLName;
+ ret = mFreeList[i].front().mClientData;
+
+ sBytesPooled -= size;
+
+ mFreeList[i].pop_front();
+ }
+
+ return ret;
+}
+
+void LLVBOPool::release(U32 name, U8* buffer, U32 size)
+{
+ llassert(nhpo2(size) == size);
+
+ U32 i = wpo2(size);
+
+ llassert(mFreeList.size() > i);
+
+ Record rec;
+ rec.mGLName = name;
+ rec.mClientData = buffer;
+
+ sBytesPooled += size;
+
+ mFreeList[i].push_back(rec);
+}
+
+void LLVBOPool::cleanup()
+{
+ U32 size = 1;
+
+ for (U32 i = 0; i < mFreeList.size(); ++i)
+ {
+ record_list_t& l = mFreeList[i];
+
+ while (!l.empty())
+ {
+ Record& r = l.front();
+
+ glDeleteBuffersARB(1, &r.mGLName);
+
+ if (r.mClientData)
+ {
+ ll_aligned_free_16(r.mClientData);
+ }
+
+ l.pop_front();
+
+ LLVertexBuffer::sAllocatedBytes -= size;
+ }
+
+ size *= 2;
+ }
+}
+
+
//NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware
S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
{
@@ -374,16 +486,16 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
{
- if (start >= (U32) mRequestedNumVerts ||
- end >= (U32) mRequestedNumVerts)
+ if (start >= (U32) mNumVerts ||
+ end >= (U32) mNumVerts)
{
- llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl;
+ llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << llendl;
}
- llassert(mRequestedNumIndices >= 0);
+ llassert(mNumIndices >= 0);
- if (indices_offset >= (U32) mRequestedNumIndices ||
- indices_offset + count > (U32) mRequestedNumIndices)
+ if (indices_offset >= (U32) mNumIndices ||
+ indices_offset + count > (U32) mNumIndices)
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
@@ -407,7 +519,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
gGL.syncMatrices();
- llassert(mRequestedNumVerts >= 0);
+ llassert(mNumVerts >= 0);
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
if (mGLArray)
@@ -462,9 +574,9 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
gGL.syncMatrices();
- llassert(mRequestedNumIndices >= 0);
- if (indices_offset >= (U32) mRequestedNumIndices ||
- indices_offset + count > (U32) mRequestedNumIndices)
+ llassert(mNumIndices >= 0);
+ if (indices_offset >= (U32) mNumIndices ||
+ indices_offset + count > (U32) mNumIndices)
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
@@ -508,9 +620,9 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
gGL.syncMatrices();
- llassert(mRequestedNumVerts >= 0);
- if (first >= (U32) mRequestedNumVerts ||
- first + count > (U32) mRequestedNumVerts)
+ llassert(mNumVerts >= 0);
+ if (first >= (U32) mNumVerts ||
+ first + count > (U32) mNumVerts)
{
llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
}
@@ -546,23 +658,22 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
{
sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
- if(sEnableVBOs)
- {
- //llassert_always(glBindBufferARB) ; //double check the extention for VBO is loaded.
-
- llinfos << "VBO is enabled." << llendl ;
- }
- else
- {
- llinfos << "VBO is disabled." << llendl ;
- }
-
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
if(!sPrivatePoolp)
{
sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ;
}
+
+ sStreamVBOPool.mType = GL_ARRAY_BUFFER_ARB;
+ sStreamVBOPool.mUsage= GL_STREAM_DRAW_ARB;
+ sStreamIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
+ sStreamIBOPool.mUsage= GL_STREAM_DRAW_ARB;
+
+ sDynamicVBOPool.mType = GL_ARRAY_BUFFER_ARB;
+ sDynamicVBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
+ sDynamicIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
+ sDynamicIBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
}
//static
@@ -600,7 +711,11 @@ void LLVertexBuffer::cleanupClass()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS);
unbind();
- clientCopy(); // deletes GL buffers
+
+ sStreamIBOPool.cleanup();
+ sDynamicIBOPool.cleanup();
+ sStreamVBOPool.cleanup();
+ sDynamicVBOPool.cleanup();
if(sPrivatePoolp)
{
@@ -609,15 +724,6 @@ void LLVertexBuffer::cleanupClass()
}
}
-void LLVertexBuffer::clientCopy(F64 max_time)
-{
- if (!sDeleteList.empty())
- {
- glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
- sDeleteList.clear();
- }
-}
-
//----------------------------------------------------------------------------
LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
@@ -625,8 +731,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mNumVerts(0),
mNumIndices(0),
- mRequestedNumVerts(-1),
- mRequestedNumIndices(-1),
mUsage(usage),
mGLBuffer(0),
mGLArray(0),
@@ -636,10 +740,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mVertexLocked(FALSE),
mIndexLocked(FALSE),
mFinal(FALSE),
- mFilthy(FALSE),
mEmpty(TRUE),
- mResized(FALSE),
- mDynamicSize(FALSE),
mFence(NULL)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
@@ -664,6 +765,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mUsage = GL_STREAM_DRAW_ARB;
}
+ if (mUsage && mUsage != GL_STREAM_DRAW_ARB)
+ { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
+ mUsage = GL_DYNAMIC_DRAW_ARB;
+ }
+
//zero out offsets
for (U32 i = 0; i < TYPE_MAX; i++)
{
@@ -672,6 +778,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mTypeMask = typemask;
mSize = 0;
+ mIndicesSize = 0;
mAlignedOffset = 0;
mAlignedIndexOffset = 0;
@@ -775,39 +882,35 @@ void LLVertexBuffer::waitFence() const
//----------------------------------------------------------------------------
-void LLVertexBuffer::genBuffer()
+void LLVertexBuffer::genBuffer(U32 size)
{
+ mSize = nhpo2(size);
+
if (mUsage == GL_STREAM_DRAW_ARB)
{
- mGLBuffer = sStreamVBOPool.allocate();
- }
- else if (mUsage == GL_DYNAMIC_DRAW_ARB)
- {
- mGLBuffer = sDynamicVBOPool.allocate();
+ mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
}
else
{
- BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
- glGenBuffersARB(1, (GLuint*)&mGLBuffer);
+ mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
}
+
sGLCount++;
}
-void LLVertexBuffer::genIndices()
+void LLVertexBuffer::genIndices(U32 size)
{
+ mIndicesSize = nhpo2(size);
+
if (mUsage == GL_STREAM_DRAW_ARB)
{
- mGLIndices = sStreamIBOPool.allocate();
- }
- else if (mUsage == GL_DYNAMIC_DRAW_ARB)
- {
- mGLIndices = sDynamicIBOPool.allocate();
+ mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize);
}
else
{
- BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
- glGenBuffersARB(1, (GLuint*)&mGLIndices);
+ mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
}
+
sGLCount++;
}
@@ -815,16 +918,16 @@ void LLVertexBuffer::releaseBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
- sStreamVBOPool.release(mGLBuffer);
- }
- else if (mUsage == GL_DYNAMIC_DRAW_ARB)
- {
- sDynamicVBOPool.release(mGLBuffer);
+ sStreamVBOPool.release(mGLBuffer, mMappedData, mSize);
}
else
{
- sDeleteList.push_back(mGLBuffer);
+ sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize);
}
+
+ mGLBuffer = 0;
+ mMappedData = NULL;
+
sGLCount--;
}
@@ -832,24 +935,23 @@ void LLVertexBuffer::releaseIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
- sStreamIBOPool.release(mGLIndices);
+ sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
- sDynamicIBOPool.release(mGLIndices);
- }
- else
- {
- sDeleteList.push_back(mGLIndices);
+ sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
+
+ mGLIndices = 0;
+ mMappedIndexData = NULL;
+
sGLCount--;
}
-void LLVertexBuffer::createGLBuffer()
+void LLVertexBuffer::createGLBuffer(U32 size)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_VERTICES);
- U32 size = getSize();
if (mGLBuffer)
{
destroyGLBuffer();
@@ -864,23 +966,21 @@ void LLVertexBuffer::createGLBuffer()
if (useVBOs())
{
- mMappedData = NULL;
- genBuffer();
- mResized = TRUE;
+ genBuffer(size);
}
else
{
static int gl_buffer_idx = 0;
mGLBuffer = ++gl_buffer_idx;
mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
+ mSize = size;
}
}
-void LLVertexBuffer::createGLIndices()
+void LLVertexBuffer::createGLIndices(U32 size)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_INDICES);
- U32 size = getIndicesSize();
-
+
if (mGLIndices)
{
destroyGLIndices();
@@ -900,15 +1000,14 @@ void LLVertexBuffer::createGLIndices()
{
//pad by another 16 bytes for VBO pointer adjustment
size += 16;
- mMappedIndexData = NULL;
- genIndices();
- mResized = TRUE;
+ genIndices(size);
}
else
{
mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
static int gl_buffer_idx = 0;
mGLIndices = ++gl_buffer_idx;
+ mIndicesSize = size;
}
}
@@ -919,12 +1018,6 @@ void LLVertexBuffer::destroyGLBuffer()
{
if (useVBOs())
{
- freeClientBuffer() ;
-
- if (mMappedData || mMappedIndexData)
- {
- llerrs << "Vertex buffer destroyed while mapped!" << llendl;
- }
releaseBuffer();
}
else
@@ -933,8 +1026,6 @@ void LLVertexBuffer::destroyGLBuffer()
mMappedData = NULL;
mEmpty = TRUE;
}
-
- sAllocatedBytes -= getSize();
}
mGLBuffer = 0;
@@ -948,12 +1039,6 @@ void LLVertexBuffer::destroyGLIndices()
{
if (useVBOs())
{
- freeClientBuffer() ;
-
- if (mMappedData || mMappedIndexData)
- {
- llerrs << "Vertex buffer destroyed while mapped." << llendl;
- }
releaseIndices();
}
else
@@ -962,8 +1047,6 @@ void LLVertexBuffer::destroyGLIndices()
mMappedIndexData = NULL;
mEmpty = TRUE;
}
-
- sAllocatedBytes -= getIndicesSize();
}
mGLIndices = 0;
@@ -982,23 +1065,14 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
nverts = 65535;
}
- mRequestedNumVerts = nverts;
+ U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
- if (!mDynamicSize)
+ if (needed_size > mSize || needed_size <= mSize/2)
{
- mNumVerts = nverts;
- }
- else if (mUsage == GL_STATIC_DRAW_ARB ||
- nverts > mNumVerts ||
- nverts < mNumVerts/2)
- {
- if (mUsage != GL_STATIC_DRAW_ARB && nverts + nverts/4 <= 65535)
- {
- nverts += nverts/4;
- }
- mNumVerts = nverts;
+ createGLBuffer(needed_size);
}
- mSize = calcOffsets(mTypeMask, mOffsets, mNumVerts);
+
+ mNumVerts = nverts;
}
void LLVertexBuffer::updateNumIndices(S32 nindices)
@@ -1007,22 +1081,14 @@ void LLVertexBuffer::updateNumIndices(S32 nindices)
llassert(nindices >= 0);
- mRequestedNumIndices = nindices;
- if (!mDynamicSize)
+ U32 needed_size = sizeof(U16) * nindices;
+
+ if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
{
- mNumIndices = nindices;
+ createGLIndices(needed_size);
}
- else if (mUsage == GL_STATIC_DRAW_ARB ||
- nindices > mNumIndices ||
- nindices < mNumIndices/2)
- {
- if (mUsage != GL_STATIC_DRAW_ARB)
- {
- nindices += nindices/4;
- }
- mNumIndices = nindices;
- }
+ mNumIndices = nindices;
}
void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
@@ -1040,15 +1106,8 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
updateNumVerts(nverts);
updateNumIndices(nindices);
- if (mMappedData)
- {
- llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl;
- }
if (create && (nverts || nindices))
{
- createGLBuffer();
- createGLIndices();
-
//actually allocate space for the vertex buffer if using VBO mapping
flush();
@@ -1060,8 +1119,6 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
setupVertexArray();
}
}
-
- sAllocatedBytes += getSize() + getIndicesSize();
}
void LLVertexBuffer::setupVertexArray()
@@ -1151,77 +1208,13 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
llassert(newnverts >= 0);
llassert(newnindices >= 0);
- mRequestedNumVerts = newnverts;
- mRequestedNumIndices = newnindices;
-
LLMemType mt2(LLMemType::MTYPE_VERTEX_RESIZE_BUFFER);
- mDynamicSize = TRUE;
- if (mUsage == GL_STATIC_DRAW_ARB)
- { //always delete/allocate static buffers on resize
- destroyGLBuffer();
- destroyGLIndices();
- allocateBuffer(newnverts, newnindices, TRUE);
- mFinal = FALSE;
- }
- else if (newnverts > mNumVerts || newnindices > mNumIndices ||
- newnverts < mNumVerts/2 || newnindices < mNumIndices/2)
- {
- sAllocatedBytes -= getSize() + getIndicesSize();
-
- updateNumVerts(newnverts);
- updateNumIndices(newnindices);
-
- S32 newsize = getSize();
- S32 new_index_size = getIndicesSize();
-
- sAllocatedBytes += newsize + new_index_size;
-
- if (newsize)
- {
- if (!mGLBuffer)
- { //no buffer exists, create a new one
- createGLBuffer();
- }
- else
- {
- if (!useVBOs())
- {
- FREE_MEM(sPrivatePoolp, mMappedData);
- mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, newsize);
- }
- mResized = TRUE;
- }
- }
- else if (mGLBuffer)
- {
- destroyGLBuffer();
- }
-
- if (new_index_size)
- {
- if (!mGLIndices)
- {
- createGLIndices();
- }
- else
- {
- if (!useVBOs())
- {
- FREE_MEM(sPrivatePoolp, mMappedIndexData) ;
- mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, new_index_size);
- }
- mResized = TRUE;
- }
- }
- else if (mGLIndices)
- {
- destroyGLIndices();
- }
- }
-
- if (mResized && useVBOs())
+
+ updateNumVerts(newnverts);
+ updateNumIndices(newnindices);
+
+ if (useVBOs())
{
- freeClientBuffer();
flush();
if (mGLArray)
@@ -1244,32 +1237,6 @@ BOOL LLVertexBuffer::useVBOs() const
}
//----------------------------------------------------------------------------
-void LLVertexBuffer::freeClientBuffer()
-{
- if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData))
- {
- FREE_MEM(sPrivatePoolp, mMappedData) ;
- FREE_MEM(sPrivatePoolp, mMappedIndexData) ;
- mMappedData = NULL ;
- mMappedIndexData = NULL ;
- }
-}
-
-void LLVertexBuffer::allocateClientVertexBuffer()
-{
- if(!mMappedData)
- {
- mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getSize());
- }
-}
-
-void LLVertexBuffer::allocateClientIndexBuffer()
-{
- if(!mMappedIndexData)
- {
- mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getIndicesSize());
- }
-}
bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
{
@@ -1350,7 +1317,6 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
if(sDisableVBOMapping)
{
map_range = false;
- allocateClientVertexBuffer() ;
}
else
{
@@ -1535,7 +1501,6 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
if(sDisableVBOMapping)
{
map_range = false;
- allocateClientIndexBuffer() ;
}
else
{
@@ -1772,21 +1737,7 @@ void LLVertexBuffer::unmapBuffer()
if(updated_all)
{
- if(mUsage == GL_STATIC_DRAW_ARB)
- {
- //static draw buffers can only be mapped a single time
- //throw out client data (we won't be using it again)
- mEmpty = TRUE;
- mFinal = TRUE;
- if(sDisableVBOMapping)
- {
- freeClientBuffer() ;
- }
- }
- else
- {
- mEmpty = FALSE;
- }
+ mEmpty = FALSE;
}
}
@@ -1965,27 +1916,6 @@ void LLVertexBuffer::flush()
{
if (useVBOs())
{
- if (mResized)
- {
- if (mGLBuffer)
- {
- stop_glerror();
- bindGLBuffer(true);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage);
- stop_glerror();
- }
- if (mGLIndices)
- {
- stop_glerror();
- bindGLIndices(true);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage);
- stop_glerror();
- }
-
- mEmpty = TRUE;
- mResized = FALSE;
- }
-
unmapBuffer();
}
}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index b50c409c49..3e6f6a959a 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -51,24 +51,32 @@
//============================================================================
// gl name pools for dynamic and streaming buffers
-class LLVBOPool : public LLGLNamePool
+class LLVBOPool
{
-protected:
- virtual GLuint allocateName()
- {
- GLuint name;
- stop_glerror();
- glGenBuffersARB(1, &name);
- stop_glerror();
- return name;
- }
+public:
+ static U32 sBytesPooled;
+
+ U32 mUsage;
+ U32 mType;
- virtual void releaseName(GLuint name)
+ //size MUST be a power of 2
+ U8* allocate(U32& name, U32 size);
+
+ //size MUST be the size provided to allocate that returned the given name
+ void release(U32 name, U8* buffer, U32 size);
+
+ //destroy all records in mFreeList
+ void cleanup();
+
+ class Record
{
- stop_glerror();
- glDeleteBuffersARB(1, &name);
- stop_glerror();
- }
+ public:
+ U32 mGLName;
+ U8* mClientData;
+ };
+
+ typedef std::list<Record> record_list_t;
+ std::vector<record_list_t> mFreeList;
};
class LLGLFence
@@ -120,8 +128,7 @@ public:
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp);
- static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
- static void unbind(); //unbind any bound vertex buffer
+ static void unbind(); //unbind any bound vertex buffer
//get the size of a vertex with the given typemask
static S32 calcVertexSize(const U32& typemask);
@@ -181,25 +188,22 @@ protected:
virtual void setupVertexBuffer(U32 data_mask); // pure virtual, called from mapBuffer()
void setupVertexArray();
- void genBuffer();
- void genIndices();
+ void genBuffer(U32 size);
+ void genIndices(U32 size);
bool bindGLBuffer(bool force_bind = false);
bool bindGLIndices(bool force_bind = false);
bool bindGLArray();
void releaseBuffer();
void releaseIndices();
- void createGLBuffer();
- void createGLIndices();
+ void createGLBuffer(U32 size);
+ void createGLIndices(U32 size);
void destroyGLBuffer();
void destroyGLIndices();
void updateNumVerts(S32 nverts);
void updateNumIndices(S32 nindices);
virtual BOOL useVBOs() const;
void unmapBuffer();
- void freeClientBuffer() ;
- void allocateClientVertexBuffer() ;
- void allocateClientIndexBuffer() ;
-
+
public:
LLVertexBuffer(U32 typemask, S32 usage);
@@ -239,15 +243,13 @@ public:
BOOL isLocked() const { return mVertexLocked || mIndexLocked; }
S32 getNumVerts() const { return mNumVerts; }
S32 getNumIndices() const { return mNumIndices; }
- S32 getRequestedVerts() const { return mRequestedNumVerts; }
- S32 getRequestedIndices() const { return mRequestedNumIndices; }
-
+
U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
U32 getTypeMask() const { return mTypeMask; }
bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); }
S32 getSize() const;
- S32 getIndicesSize() const { return mNumIndices * sizeof(U16); }
+ S32 getIndicesSize() const { return mIndicesSize; }
U8* getMappedData() const { return mMappedData; }
U8* getMappedIndices() const { return mMappedIndexData; }
S32 getOffset(S32 type) const { return mOffsets[type]; }
@@ -265,12 +267,11 @@ public:
protected:
S32 mNumVerts; // Number of vertices allocated
S32 mNumIndices; // Number of indices allocated
- S32 mRequestedNumVerts; // Number of vertices requested
- S32 mRequestedNumIndices; // Number of indices requested
-
+
ptrdiff_t mAlignedOffset;
ptrdiff_t mAlignedIndexOffset;
S32 mSize;
+ S32 mIndicesSize;
U32 mTypeMask;
S32 mUsage; // GL usage
U32 mGLBuffer; // GL VBO handle
@@ -282,10 +283,7 @@ protected:
BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory
BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory
BOOL mFinal; // if TRUE, buffer can not be mapped again
- BOOL mFilthy; // if TRUE, entire buffer must be copied (used to prevent redundant dirty flags)
BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded.
- BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not
- BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
S32 mOffsets[TYPE_MAX];
std::vector<MappedRegion> mMappedVertexRegions;
@@ -305,7 +303,6 @@ public:
static S32 sGLCount;
static S32 sMappedCount;
static BOOL sMapped;
- static std::vector<U32> sDeleteList;
typedef std::list<LLVertexBuffer*> buffer_list_t;
static BOOL sDisableVBOMapping; //disable glMapBufferARB
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index a710bdcdbd..7290a48a1a 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1277,8 +1277,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
if (buffer.isNull() ||
buffer->getTypeMask() != data_mask ||
- buffer->getRequestedVerts() != vol_face.mNumVertices ||
- buffer->getRequestedIndices() != vol_face.mNumIndices ||
+ buffer->getNumVerts() != vol_face.mNumVertices ||
+ buffer->getNumIndices() != vol_face.mNumIndices ||
(drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
{
face->setGeomIndex(0);
@@ -1366,7 +1366,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
- for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
+ for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4a final_mat;
final_mat.clear();
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 3fe5b4d929..cdf6e1ab52 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -113,8 +113,8 @@ void LLDrawPoolTree::render(S32 pass)
if(buff)
{
buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
- buff->drawRange(LLRender::TRIANGLES, 0, buff->getRequestedVerts()-1, buff->getRequestedIndices(), 0);
- gPipeline.addTrianglesDrawn(buff->getRequestedIndices());
+ buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
+ gPipeline.addTrianglesDrawn(buff->getNumIndices());
}
}
}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 36b88ebbd4..eab3dcfadd 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -362,8 +362,8 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
{
if (align)
{
- //allocate vertices in blocks of 16 for alignment
- num_vertices = (num_vertices + 0xF) & ~0xF;
+ //allocate vertices in blocks of 4 for alignment
+ num_vertices = (num_vertices + 0x3) & ~0x3;
}
if (mGeomCount != num_vertices ||
@@ -1073,6 +1073,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
S32 num_vertices = (S32)vf.mNumVertices;
S32 num_indices = (S32) vf.mNumIndices;
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
+ {
+ updateRebuildFlags();
+ }
+
bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
if (mVertexBuffer.notNull())
@@ -2055,7 +2060,7 @@ BOOL LLFace::verify(const U32* indices_array) const
}
// First, check whether the face data fits within the pool's range.
- if ((mGeomIndex + mGeomCount) > mVertexBuffer->getRequestedVerts())
+ if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts())
{
ok = FALSE;
llinfos << "Face references invalid vertices!" << llendl;
@@ -2074,7 +2079,7 @@ BOOL LLFace::verify(const U32* indices_array) const
llinfos << "Face has bogus indices count" << llendl;
}
- if (mIndicesIndex + mIndicesCount > mVertexBuffer->getRequestedIndices())
+ if (mIndicesIndex + mIndicesCount > mVertexBuffer->getNumIndices())
{
ok = FALSE;
llinfos << "Face references invalid indices!" << llendl;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index d9ce72a2c2..8f6013f2d9 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -5457,7 +5457,7 @@ BOOL LLModelPreview::render()
}
}
- for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
+ for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4 final_mat;
final_mat.mMatrix[0][0] = final_mat.mMatrix[1][1] = final_mat.mMatrix[2][2] = final_mat.mMatrix[3][3] = 0.f;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index ffb0ce4056..2530f1f0d4 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2454,7 +2454,7 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
if (buffer)
{
buffer->setBuffer(mask);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getRequestedVerts()-1, buffer->getRequestedIndices(), 0);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
}
}
@@ -2526,7 +2526,7 @@ void renderOctree(LLSpatialGroup* group)
//coded by buffer usage and activity
gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
LLVector4 col;
- /*if (group->mBuilt > 0.f)
+ if (group->mBuilt > 0.f)
{
group->mBuilt -= 2.f * gFrameIntervalSeconds;
if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
@@ -2595,7 +2595,7 @@ void renderOctree(LLSpatialGroup* group)
gGL.diffuseColor4f(1,1,1,1);
}
}
- else*/
+ else
{
if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty()
&& group->mSpatialPartition->mRenderByGroup)
@@ -3442,11 +3442,11 @@ void renderPhysicsShapes(LLSpatialGroup* group)
buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
gGL.diffuseColor3f(0.2f, 0.5f, 0.3f);
- buff->draw(LLRender::TRIANGLES, buff->getRequestedIndices(), 0);
+ buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
gGL.diffuseColor3f(0.2f, 1.f, 0.3f);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- buff->draw(LLRender::TRIANGLES, buff->getRequestedIndices(), 0);
+ buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
}
}
}
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 1832416a4b..e0359cc61d 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -661,10 +661,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
- {
- LLFastTimer ftm(FTM_CLIENT_COPY);
- LLVertexBuffer::clientCopy(0.016);
- }
if (gResizeScreenTexture)
{
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2aac43d99e..f3e9bc711a 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -532,7 +532,7 @@ public:
}
- addText(xpos, ypos, llformat("%d MB Vertex Data", LLVertexBuffer::sAllocatedBytes/(1024*1024)));
+ addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024)));
ypos += y_inc;
addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 5687ba5064..6506938766 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2117,8 +2117,8 @@ void LLVOAvatar::updateMeshData()
}
else
{
- if (buff->getRequestedIndices() == num_indices &&
- buff->getRequestedVerts() == num_vertices)
+ if (buff->getNumIndices() == num_indices &&
+ buff->getNumVerts() == num_vertices)
{
terse_update = true;
}
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 14fd0a1eb1..f1c5499d84 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -516,9 +516,9 @@ void LLVOWLSky::drawDome(void)
strips_segment->drawRange(
LLRender::TRIANGLE_STRIP,
- 0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(),
+ 0, strips_segment->getNumVerts()-1, strips_segment->getNumIndices(),
0);
- gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices(), LLRender::TRIANGLE_STRIP);
+ gPipeline.addTrianglesDrawn(strips_segment->getNumIndices(), LLRender::TRIANGLE_STRIP);
}
#else
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e4125c8dc8..5035e0197d 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -264,15 +264,7 @@ std::string gPoolNames[] =
void drawBox(const LLVector3& c, const LLVector3& r);
void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
-
-U32 nhpo2(U32 v)
-{
- U32 r = 1;
- while (r < v) {
- r *= 2;
- }
- return r;
-}
+U32 nhpo2(U32 v);
glh::matrix4f glh_copy_matrix(F32* src)
{
@@ -2902,11 +2894,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
}
- {
- LLFastTimer ftm(FTM_CLIENT_COPY);
- LLVertexBuffer::clientCopy();
- }
-
+
postSort(camera);
}
@@ -6122,13 +6110,7 @@ void LLPipeline::resetVertexBuffers()
llwarns << "VBO wipe failed." << llendl;
}
- if (!LLVertexBuffer::sStreamIBOPool.mNameList.empty() ||
- !LLVertexBuffer::sStreamVBOPool.mNameList.empty() ||
- !LLVertexBuffer::sDynamicIBOPool.mNameList.empty() ||
- !LLVertexBuffer::sDynamicVBOPool.mNameList.empty())
- {
- llwarns << "VBO name pool cleanup failed." << llendl;
- }
+ llassert(LLVertexBuffer::sGLCount == 0);
LLVertexBuffer::unbind();
@@ -6142,6 +6124,8 @@ void LLPipeline::resetVertexBuffers()
sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
+
+ LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
}
void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)