Newer
Older
/**
* @file llvertexbuffer.cpp
* @brief LLVertexBuffer implementation
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
#include "linden_common.h"
#include <boost/static_assert.hpp>
#include "llsys.h"
#include "llvertexbuffer.h"
// #include "llrender.h"
#include "llglheaders.h"
#include "llmemtype.h"
#include "llrender.h"
David Parks
committed
#include "llshadermgr.h"
#include "llglslshader.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;
}
//============================================================================
//static
LLVBOPool LLVertexBuffer::sStreamVBOPool;
LLVBOPool LLVertexBuffer::sDynamicVBOPool;
LLVBOPool LLVertexBuffer::sStreamIBOPool;
LLVBOPool LLVertexBuffer::sDynamicIBOPool;
U32 LLVBOPool::sBytesPooled = 0;
LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
U32 LLVertexBuffer::sBindCount = 0;
U32 LLVertexBuffer::sSetCount = 0;
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
S32 LLVertexBuffer::sMappedCount = 0;
Xiaohong Bao
committed
BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
BOOL LLVertexBuffer::sEnableVBOs = TRUE;
Josh Bell
committed
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderArray = 0;
Josh Bell
committed
U32 LLVertexBuffer::sGLRenderIndices = 0;
U32 LLVertexBuffer::sLastMask = 0;
BOOL LLVertexBuffer::sVBOActive = FALSE;
BOOL LLVertexBuffer::sIBOActive = FALSE;
U32 LLVertexBuffer::sAllocatedBytes = 0;
BOOL LLVertexBuffer::sMapped = FALSE;
BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
BOOL LLVertexBuffer::sUseVAO = FALSE;
BOOL LLVertexBuffer::sPreferStreamDraw = FALSE;
David Parks
committed
const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms
class LLGLSyncFence : public LLGLFence
{
public:
David Parks
committed
GLsync mSync;
David Parks
committed
LLGLSyncFence()
{
David Parks
committed
mSync = 0;
David Parks
committed
}
virtual ~LLGLSyncFence()
David Parks
committed
{
David Parks
committed
#ifdef GL_ARB_sync
David Parks
committed
if (mSync)
{
glDeleteSync(mSync);
}
David Parks
committed
#endif
David Parks
committed
}
void placeFence()
{
David Parks
committed
#ifdef GL_ARB_sync
David Parks
committed
if (mSync)
{
glDeleteSync(mSync);
}
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
David Parks
committed
#endif
David Parks
committed
}
void wait()
{
David Parks
committed
#ifdef GL_ARB_sync
David Parks
committed
if (mSync)
{
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
{ //track the number of times we've waited here
static S32 waits = 0;
waits++;
}
}
David Parks
committed
}
};
//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;
}
volatile U8* LLVBOPool::allocate(U32& name, U32 size)
{
llassert(nhpo2(size) == size);
U32 i = wpo2(size);
if (mFreeList.size() <= i)
{
mFreeList.resize(i+1);
}
volatile 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 || mUsage != GL_DYNAMIC_DRAW_ARB)
{
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, volatile 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;
if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB)
{
glDeleteBuffersARB(1, &rec.mGLName);
}
else
{
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((void*) r.mClientData);
}
l.pop_front();
LLVertexBuffer::sAllocatedBytes -= size;
sBytesPooled -= size;
}
size *= 2;
}
}
David Parks
committed
//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] =
sizeof(LLVector4), // TYPE_VERTEX,
sizeof(LLVector4), // TYPE_NORMAL,
sizeof(LLVector2), // TYPE_TEXCOORD0,
sizeof(LLVector2), // TYPE_TEXCOORD1,
sizeof(LLVector2), // TYPE_TEXCOORD2,
sizeof(LLVector2), // TYPE_TEXCOORD3,
sizeof(LLColor4U), // TYPE_COLOR,
David Parks
committed
sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently
sizeof(F32), // TYPE_WEIGHT,
sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes
U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
{
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_QUADS,
GL_LINE_LOOP,
void LLVertexBuffer::setupClientArrays(U32 data_mask)
David Parks
committed
if (sLastMask != data_mask)
BOOL error = FALSE;
David Parks
committed
if (LLGLSLShader::sNoFixedFunction)
{
for (U32 i = 0; i < TYPE_MAX; ++i)
S32 loc = i;
U32 mask = 1 << i;
if (sLastMask & (1 << i))
{ //was enabled
if (!(data_mask & mask))
{ //needs to be disabled
glDisableVertexAttribArrayARB(loc);
}
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
}
else
{ //was disabled
if (data_mask & mask)
{ //needs to be enabled
glEnableVertexAttribArrayARB(loc);
}
}
}
}
else
{
GLenum array[] =
{
GL_VERTEX_ARRAY,
GL_NORMAL_ARRAY,
GL_TEXTURE_COORD_ARRAY,
GL_COLOR_ARRAY,
};
GLenum mask[] =
{
MAP_VERTEX,
MAP_NORMAL,
MAP_TEXCOORD0,
MAP_COLOR
};
for (U32 i = 0; i < 4; ++i)
{
if (sLastMask & mask[i])
{ //was enabled
if (!(data_mask & mask[i]))
{ //needs to be disabled
glDisableClientState(array[i]);
}
else if (gDebugGL)
{ //needs to be enabled, make sure it was (DEBUG)
if (!glIsEnabled(array[i]))
{
if (gDebugSession)
{
error = TRUE;
gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
}
else
{
llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
}
}
}
else
{ //was disabled
if (data_mask & mask[i])
{ //needs to be enabled
glEnableClientState(array[i]);
}
else if (gDebugGL && glIsEnabled(array[i]))
{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
if (gDebugSession)
{
error = TRUE;
gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
}
else
{
llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
U32 map_tc[] =
{
MAP_TEXCOORD1,
MAP_TEXCOORD2,
MAP_TEXCOORD3
};
David Parks
committed
for (U32 i = 0; i < 3; i++)
if (sLastMask & map_tc[i])
{
if (!(data_mask & map_tc[i]))
{ //disable
glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
else if (data_mask & map_tc[i])
{
glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
}
David Parks
committed
if (sLastMask & MAP_BINORMAL)
if (!(data_mask & MAP_BINORMAL))
{
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
else if (data_mask & MAP_BINORMAL)
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
David Parks
committed
sLastMask = data_mask;
//static
void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm)
David Parks
committed
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
gGL.syncMatrices();
David Parks
committed
Xiaohong Bao
committed
llassert_always(norm.size() >= pos.size());
llassert_always(count > 0) ;
unbind();
setupClientArrays(MAP_VERTEX | MAP_NORMAL);
David Parks
committed
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
if (shader)
{
David Parks
committed
S32 loc = LLVertexBuffer::TYPE_VERTEX;
David Parks
committed
if (loc > -1)
{
glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV);
}
David Parks
committed
loc = LLVertexBuffer::TYPE_NORMAL;
David Parks
committed
if (loc > -1)
{
glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV);
}
}
else
{
glVertexPointer(3, GL_FLOAT, 0, pos[0].mV);
glNormalPointer(GL_FLOAT, 0, norm[0].mV);
}
glDrawArrays(sGLMode[mode], 0, count);
}
David Parks
committed
//static
void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp)
{
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
gGL.syncMatrices();
David Parks
committed
U32 mask = LLVertexBuffer::MAP_VERTEX;
if (tc)
{
mask = mask | LLVertexBuffer::MAP_TEXCOORD0;
}
unbind();
setupClientArrays(mask);
David Parks
committed
if (LLGLSLShader::sNoFixedFunction)
David Parks
committed
{
David Parks
committed
S32 loc = LLVertexBuffer::TYPE_VERTEX;
glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos);
David Parks
committed
David Parks
committed
if (tc)
{
loc = LLVertexBuffer::TYPE_TEXCOORD0;
glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc);
David Parks
committed
}
}
else
{
glTexCoordPointer(2, GL_FLOAT, 0, tc);
glVertexPointer(3, GL_FLOAT, 16, pos);
}
glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp);
}
void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
if (start >= (U32) mNumVerts ||
end >= (U32) mNumVerts)
llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << llendl;
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;
}
if (gDebugGL && !useVBOs())
{
U16* idx = ((U16*) getIndicesPointer())+indices_offset;
for (U32 i = 0; i < count; ++i)
{
if (idx[i] < start || idx[i] > end)
{
llerrs << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << llendl;
}
}
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
{
LLStrider<LLVector4a> v;
//hack to get non-const reference
LLVertexBuffer* vb = (LLVertexBuffer*) this;
vb->getVertexStrider(v);
for (U32 i = start; i < end; i++)
{
S32 idx = (S32) (v[i][3]+0.25f);
if (idx < 0 || idx >= shader->mFeatures.mIndexedTextureChannels)
{
llerrs << "Bad texture index found in vertex data stream." << llendl;
}
}
}
}
}
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
validateRange(start, end, count, indices_offset);
mMappable = FALSE;
gGL.syncMatrices();
llassert(mNumVerts >= 0);
David Parks
committed
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
David Parks
committed
if (mGLArray)
David Parks
committed
if (mGLArray != sGLRenderArray)
{
llerrs << "Wrong vertex array bound." << llendl;
}
David Parks
committed
else
{
if (mGLIndices != sGLRenderIndices)
{
llerrs << "Wrong index buffer bound." << llendl;
}
David Parks
committed
if (mGLBuffer != sGLRenderBuffer)
{
llerrs << "Wrong vertex buffer bound." << llendl;
}
}
if (gDebugGL && !mGLArray && useVBOs())
David Parks
committed
GLint elem = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
if (elem != mGLIndices)
{
llerrs << "Wrong index buffer bound!" << llendl;
}
{
llerrs << "Invalid draw mode: " << mode << llendl;
stop_glerror();
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
David Parks
committed
placeFence();
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
David Parks
committed
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
mMappable = FALSE;
gGL.syncMatrices();
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;
}
David Parks
committed
if (mGLArray)
David Parks
committed
if (mGLArray != sGLRenderArray)
{
llerrs << "Wrong vertex array bound." << llendl;
}
David Parks
committed
else
David Parks
committed
if (mGLIndices != sGLRenderIndices)
{
llerrs << "Wrong index buffer bound." << llendl;
}
if (mGLBuffer != sGLRenderBuffer)
{
llerrs << "Wrong vertex buffer bound." << llendl;
}
{
llerrs << "Invalid draw mode: " << mode << llendl;
stop_glerror();
glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
stop_glerror();
David Parks
committed
placeFence();
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
David Parks
committed
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
mMappable = FALSE;
gGL.syncMatrices();
llassert(mNumVerts >= 0);
if (first >= (U32) mNumVerts ||
first + count > (U32) mNumVerts)
{
llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
}
David Parks
committed
if (mGLArray)
David Parks
committed
if (mGLArray != sGLRenderArray)
{
llerrs << "Wrong vertex array bound." << llendl;
}
}
else
{
if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
{
llerrs << "Wrong vertex buffer bound." << llendl;
}
{
llerrs << "Invalid draw mode: " << mode << llendl;
stop_glerror();
glDrawArrays(sGLMode[mode], first, count);
David Parks
committed
placeFence();
Xiaohong Bao
committed
void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
Xiaohong Bao
committed
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
{
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
void LLVertexBuffer::unbind()
{
if (sGLRenderArray)
{
glBindVertexArray(0);
sGLRenderArray = 0;
David Parks
committed
sGLRenderIndices = 0;
sIBOActive = FALSE;
}
if (sVBOActive)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
sVBOActive = FALSE;
}
if (sIBOActive)
{
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
sIBOActive = FALSE;
}
sGLRenderBuffer = 0;
sGLRenderIndices = 0;
}
//static
void LLVertexBuffer::cleanupClass()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS);
sStreamIBOPool.cleanup();
sDynamicIBOPool.cleanup();
sStreamVBOPool.cleanup();
sDynamicVBOPool.cleanup();
if(sPrivatePoolp)
{
LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
sPrivatePoolp = NULL ;
}
}
//----------------------------------------------------------------------------
LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
LLRefCount(),
mNumVerts(0),
mNumIndices(0),
mUsage(usage),
mGLBuffer(0),
mGLArray(0),
Xiaohong Bao
committed
mMappedIndexData(NULL),
mVertexLocked(FALSE),
mIndexLocked(FALSE),
Josh Bell
committed
mFinal(FALSE),
mEmpty(TRUE),
David Parks
committed
mFence(NULL)
LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
David Parks
committed
mFence = NULL;
if (!sEnableVBOs)
{
mUsage = 0 ;
if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
{
mUsage = 0;
}
if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
mUsage = GL_STREAM_DRAW_ARB;
if (mUsage == 0 && LLRender::sGLCoreProfile)
{ //MUST use VBOs for all rendering
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;
}
if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping)
{
mMappable = TRUE;
}
else
{
mMappable = FALSE;
}
//zero out offsets
for (U32 i = 0; i < TYPE_MAX; i++)
{
mOffsets[i] = 0;
}
mTypeMask = typemask;
mSize = 0;
mIndicesSize = 0;
sCount++;
}
//static
S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices)
{
for (S32 i=0; i<TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
if (offsets && LLVertexBuffer::sTypeSize[i])
{
offset += LLVertexBuffer::sTypeSize[i]*num_vertices;
}
offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
//static
S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
{
S32 size = 0;
for (S32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
size += LLVertexBuffer::sTypeSize[i];
return size;
{
return mSize;
}
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR);
destroyGLBuffer();
destroyGLIndices();
if (mGLArray)
{
glDeleteVertexArrays(1, &mGLArray);
}
Xiaohong Bao
committed
David Parks
committed
if (mFence)
{
delete mFence;
}
mFence = NULL;
Xiaohong Bao
committed
llassert_always(!mMappedData && !mMappedIndexData) ;
David Parks
committed
void LLVertexBuffer::placeFence() const
{
/*if (!mFence && useVBOs())
{
if (gGLManager.mHasSync)
{
mFence = new LLGLSyncFence();
}
}
if (mFence)
{
mFence->placeFence();
}*/
}
void LLVertexBuffer::waitFence() const
{
/*if (mFence)
{
mFence->wait();
}*/
}
//----------------------------------------------------------------------------
void LLVertexBuffer::genBuffer(U32 size)
{
mSize = nhpo2(size);
if (mUsage == GL_STREAM_DRAW_ARB)
{
mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
}
else
{
mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
}
sGLCount++;
}
void LLVertexBuffer::genIndices(U32 size)
{
mIndicesSize = nhpo2(size);
if (mUsage == GL_STREAM_DRAW_ARB)
{
mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize);
}
else
{
mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
}
sGLCount++;
}
void LLVertexBuffer::releaseBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamVBOPool.release(mGLBuffer, mMappedData, mSize);
}
else
{
sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize);
}
mGLBuffer = 0;
mMappedData = NULL;
sGLCount--;
}
void LLVertexBuffer::releaseIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
{
sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
mGLIndices = 0;
mMappedIndexData = NULL;
sGLCount--;
}
void LLVertexBuffer::createGLBuffer(U32 size)
LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_VERTICES);