summaryrefslogtreecommitdiff
path: root/indra/llrender/llvertexbuffer.cpp
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 /indra/llrender/llvertexbuffer.cpp
parent1a499c13c813d4aa9631ffae00b36a053f260747 (diff)
SH-1650 Mitigate memory fragmentation by holding onto and reusing VBOs
Diffstat (limited to 'indra/llrender/llvertexbuffer.cpp')
-rw-r--r--indra/llrender/llvertexbuffer.cpp458
1 files changed, 194 insertions, 264 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();
}
}