summaryrefslogtreecommitdiff
path: root/indra/llrender/llvertexbuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender/llvertexbuffer.cpp')
-rw-r--r--indra/llrender/llvertexbuffer.cpp299
1 files changed, 230 insertions, 69 deletions
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index de4501dd0f..1beb74eca6 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -27,7 +27,7 @@
#include "linden_common.h"
#include <boost/static_assert.hpp>
-
+#include "llsys.h"
#include "llvertexbuffer.h"
// #include "llrender.h"
#include "llglheaders.h"
@@ -47,6 +47,7 @@ U32 LLVertexBuffer::sSetCount = 0;
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
S32 LLVertexBuffer::sMappedCount = 0;
+BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
BOOL LLVertexBuffer::sEnableVBOs = TRUE;
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderIndices = 0;
@@ -251,6 +252,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
llassert(mRequestedNumIndices >= 0);
+
if (indices_offset >= (U32) mRequestedNumIndices ||
indices_offset + count > (U32) mRequestedNumIndices)
{
@@ -282,6 +284,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
llassert(mRequestedNumVerts >= 0);
+
if (first >= (U32) mRequestedNumVerts ||
first + count > (U32) mRequestedNumVerts)
{
@@ -305,9 +308,21 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
}
//static
-void LLVertexBuffer::initClass(bool use_vbo)
+void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
{
- sEnableVBOs = use_vbo;
+ 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 ;
LLGLNamePool::registerPool(&sDynamicVBOPool);
LLGLNamePool::registerPool(&sDynamicIBOPool);
LLGLNamePool::registerPool(&sStreamVBOPool);
@@ -364,7 +379,9 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mGLBuffer(0),
mGLIndices(0),
mMappedData(NULL),
- mMappedIndexData(NULL), mLocked(FALSE),
+ mMappedIndexData(NULL),
+ mVertexLocked(FALSE),
+ mIndexLocked(FALSE),
mFinal(FALSE),
mFilthy(FALSE),
mEmpty(TRUE),
@@ -422,6 +439,8 @@ LLVertexBuffer::~LLVertexBuffer()
destroyGLBuffer();
destroyGLIndices();
sCount--;
+
+ llassert_always(!mMappedData && !mMappedIndexData) ;
};
//----------------------------------------------------------------------------
@@ -567,6 +586,8 @@ void LLVertexBuffer::destroyGLBuffer()
{
if (useVBOs())
{
+ freeClientBuffer() ;
+
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped!" << llendl;
@@ -594,11 +615,13 @@ void LLVertexBuffer::destroyGLIndices()
{
if (useVBOs())
{
+ freeClientBuffer() ;
+
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped." << llendl;
}
- releaseIndices();
+ releaseIndices();
}
else
{
@@ -799,6 +822,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
if (mResized && useVBOs())
{
+ freeClientBuffer() ;
setBuffer(0);
}
}
@@ -822,110 +846,239 @@ BOOL LLVertexBuffer::useVBOs() const
}
//----------------------------------------------------------------------------
+void LLVertexBuffer::freeClientBuffer()
+{
+ if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData))
+ {
+ delete[] mMappedData ;
+ delete[] mMappedIndexData ;
+ mMappedData = NULL ;
+ mMappedIndexData = NULL ;
+ }
+}
+
+void LLVertexBuffer::allocateClientVertexBuffer()
+{
+ if(!mMappedData)
+ {
+ U32 size = getSize() ;
+ mMappedData = new U8[size];
+ memset(mMappedData, 0, size);
+ }
+}
+
+void LLVertexBuffer::allocateClientIndexBuffer()
+{
+ if(!mMappedIndexData)
+ {
+ U32 size = getIndicesSize();
+ mMappedIndexData = new U8[size];
+ memset(mMappedIndexData, 0, size);
+ }
+}
// Map for data access
-U8* LLVertexBuffer::mapBuffer(S32 access)
+U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
{
- llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
+ llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl;
}
if (!useVBOs() && !mMappedData && !mMappedIndexData)
{
- llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
+ llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
}
- if (!mLocked && useVBOs())
+ if (!mVertexLocked && useVBOs())
{
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
- setBuffer(0);
- mLocked = TRUE;
+ setBuffer(0, type);
+ mVertexLocked = TRUE;
stop_glerror();
- mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+
+ if(sDisableVBOMapping)
+ {
+ allocateClientVertexBuffer() ;
+ }
+ else
+ {
+ mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
stop_glerror();
}
+
+ if (!mMappedData)
{
- LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
- mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- stop_glerror();
+ log_glerror();
+
+ //check the availability of memory
+ U32 avail_phy_mem, avail_vir_mem;
+ LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
+ llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
+ llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
+
+ if(!sDisableVBOMapping)
+ {
+ //--------------------
+ //print out more debug info before crash
+ llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
+ GLint size ;
+ glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
+ llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
+ //--------------------
+
+ GLint buff;
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
+ if ((GLuint)buff != mGLBuffer)
+ {
+ llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ }
+
+
+ llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
+ }
+ else
+ {
+ llerrs << "memory allocation for vertex data failed." << llendl ;
+ }
}
+ sMappedCount++;
+ }
+
+ return mMappedData;
+}
- if (!mMappedData)
+U8* LLVertexBuffer::mapIndexBuffer(S32 access)
+{
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
+ if (mFinal)
+ {
+ llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl;
+ }
+ if (!useVBOs() && !mMappedData && !mMappedIndexData)
+ {
+ llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
+ }
+
+ if (!mIndexLocked && useVBOs())
+ {
{
- //--------------------
- //print out more debug info before crash
- llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
- GLint size ;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
- llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
- //--------------------
+ LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
+ setBuffer(0, TYPE_INDEX);
+ mIndexLocked = TRUE;
+ stop_glerror();
+
+ if(sDisableVBOMapping)
{
- llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ allocateClientIndexBuffer() ;
}
-
-
- llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
+ else
+ {
+ mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+ stop_glerror();
}
if (!mMappedIndexData)
{
- GLint buff;
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
+ log_glerror();
+
+ if(!sDisableVBOMapping)
{
- llerrs << "Invalid GL index buffer bound: " << buff << llendl;
- }
+ GLint buff;
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
+ if ((GLuint)buff != mGLIndices)
+ {
+ llerrs << "Invalid GL index buffer bound: " << buff << llendl;
+ }
- llerrs << "glMapBuffer returned NULL (no index data)" << llendl;
+ llerrs << "glMapBuffer returned NULL (no index data)" << llendl;
+ }
+ else
+ {
+ llerrs << "memory allocation for Index data failed. " << llendl ;
+ }
}
sMappedCount++;
}
-
- return mMappedData;
+
+ return mMappedIndexData ;
}
-void LLVertexBuffer::unmapBuffer()
+void LLVertexBuffer::unmapBuffer(S32 type)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
- if (mMappedData || mMappedIndexData)
+ if (!useVBOs())
+ {
+ return ; //nothing to unmap
+ }
+
+ bool updated_all = false ;
+ if (mMappedData && mVertexLocked && type != TYPE_INDEX)
{
- if (useVBOs() && mLocked)
+ updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating
+
+ if(sDisableVBOMapping)
+ {
+ stop_glerror();
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
+ stop_glerror();
+ }
+ else
{
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
+
+ mMappedData = NULL;
+ }
+
+ mVertexLocked = FALSE ;
+ sMappedCount--;
+ }
+
+ if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
+ {
+ if(sDisableVBOMapping)
+ {
+ stop_glerror();
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
+ stop_glerror();
+ }
+ else
+ {
+ stop_glerror();
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
- /*if (!sMapped)
- {
- llerrs << "Redundantly unmapped VBO!" << llendl;
- }
- sMapped = FALSE;*/
- sMappedCount--;
-
- 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;
- }
- else
+ mMappedIndexData = NULL ;
+ }
+
+ mIndexLocked = FALSE ;
+ sMappedCount--;
+ }
+
+ 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)
{
- mEmpty = FALSE;
+ freeClientBuffer() ;
}
-
- mMappedIndexData = NULL;
- mMappedData = NULL;
-
- mLocked = FALSE;
+ }
+ else
+ {
+ mEmpty = FALSE;
}
}
}
@@ -939,15 +1092,16 @@ template <class T,S32 type> struct VertexBufferStrider
strider_t& strider,
S32 index)
{
- if (vbo.mapBuffer() == NULL)
- {
- llwarns << "mapBuffer failed!" << llendl;
- return FALSE;
- }
-
if (type == LLVertexBuffer::TYPE_INDEX)
{
S32 stride = sizeof(T);
+
+ if (vbo.mapIndexBuffer() == NULL)
+ {
+ llwarns << "mapIndexBuffer failed!" << llendl;
+ return FALSE;
+ }
+
strider = (T*)(vbo.getMappedIndices() + index*stride);
strider.setStride(0);
return TRUE;
@@ -955,6 +1109,13 @@ template <class T,S32 type> struct VertexBufferStrider
else if (vbo.hasDataType(type))
{
S32 stride = vbo.getStride();
+
+ if (vbo.mapVertexBuffer(type) == NULL)
+ {
+ llwarns << "mapVertexBuffer failed!" << llendl;
+ return FALSE;
+ }
+
strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride);
strider.setStride(stride);
return TRUE;
@@ -1035,7 +1196,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride)
//----------------------------------------------------------------------------
// Set for rendering
-void LLVertexBuffer::setBuffer(U32 data_mask)
+void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
//set up pointers if the data mask is different ...
@@ -1176,7 +1337,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
ll_fail("LLVertexBuffer::mapBuffer failed");
}
- unmapBuffer();
+ unmapBuffer(type);
}
else
{