Newer
Older
Xiaohong Bao
committed
{
Leslie Linden
committed
mEmpty = false;
}
}
//----------------------------------------------------------------------------
template <class T,S32 type> struct VertexBufferStrider
{
typedef LLStrider<T> strider_t;
static bool get(LLVertexBuffer& vbo,
strider_t& strider,
S32 index, S32 count, bool map_range)
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
if (ptr == NULL)
Xiaohong Bao
committed
{
llwarns << "mapIndexBuffer failed!" << llendl;
Leslie Linden
committed
return false;
Xiaohong Bao
committed
}
strider = (T*)ptr;
strider.setStride(0);
Leslie Linden
committed
return true;
}
else if (vbo.hasDataType(type))
{
S32 stride = LLVertexBuffer::sTypeSize[type];
Xiaohong Bao
committed
volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
if (ptr == NULL)
Xiaohong Bao
committed
{
llwarns << "mapVertexBuffer failed!" << llendl;
Leslie Linden
committed
return false;
Xiaohong Bao
committed
}
strider = (T*)ptr;
strider.setStride(stride);
Leslie Linden
committed
return true;
}
else
{
llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
}
Leslie Linden
committed
return false;
bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
David Parks
committed
bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
David Parks
committed
bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
David Parks
committed
return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
David Parks
committed
bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
David Parks
committed
return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
}
//----------------------------------------------------------------------------
static LLFastTimer::DeclareTimer FTM_BIND_GL_ARRAY("Bind Array");
David Parks
committed
bool LLVertexBuffer::bindGLArray()
{
if (mGLArray && sGLRenderArray != mGLArray)
{
David Parks
committed
//really shouldn't be necessary, but some drivers don't properly restore the
//state of GL_ELEMENT_ARRAY_BUFFER_BINDING
bindGLIndices();
David Parks
committed
return true;
}
return false;
}
static LLFastTimer::DeclareTimer FTM_BIND_GL_BUFFER("Bind Buffer");
David Parks
committed
bool LLVertexBuffer::bindGLBuffer(bool force_bind)
{
bindGLArray();
bool ret = false;
if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
{
David Parks
committed
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;
}*/
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
sGLRenderBuffer = mGLBuffer;
sBindCount++;
David Parks
committed
if (mGLArray)
{
llassert(sGLRenderArray == mGLArray);
//mCachedRenderBuffer = mGLBuffer;
}
ret = true;
}
return ret;
}
static LLFastTimer::DeclareTimer FTM_BIND_GL_INDICES("Bind Indices");
David Parks
committed
bool LLVertexBuffer::bindGLIndices(bool force_bind)
{
bindGLArray();
bool ret = false;
if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))))
{
David Parks
committed
/*if (sMapped)
{
llerrs << "VBO bound while another VBO mapped!" << llendl;
}*/
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
sGLRenderIndices = mGLIndices;
stop_glerror();
sBindCount++;
David Parks
committed
ret = true;
}
return ret;
}
void LLVertexBuffer::flush()
{
if (useVBOs())
{
unmapBuffer();
}
}
David Parks
committed
// bind for transform feedback (quick 'n dirty)
void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count)
{
David Parks
committed
U32 offset = mOffsets[type] + sTypeSize[type]*index;
U32 size= (sTypeSize[type]*count);
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size);
David Parks
committed
}
// Set for rendering
David Parks
committed
void LLVertexBuffer::setBuffer(U32 data_mask)
David Parks
committed
flush();
//set up pointers if the data mask is different ...
Leslie Linden
committed
bool setup = (sLastMask != data_mask);
David Parks
committed
if (gDebugGL && data_mask != 0)
David Parks
committed
{ //make sure data requirements are fulfilled
David Parks
committed
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
if (shader)
{
U32 required_mask = 0;
David Parks
committed
for (U32 i = 0; i < LLVertexBuffer::TYPE_TEXTURE_INDEX; ++i)
David Parks
committed
{
if (shader->getAttribLocation(i) > -1)
{
U32 required = 1 << i;
if ((data_mask & required) == 0)
{
David Parks
committed
llwarns << "Missing attribute: " << LLShaderMgr::instance()->mReservedAttribs[i] << llendl;
David Parks
committed
}
required_mask |= required;
}
}
if ((data_mask & required_mask) != required_mask)
{
Graham Linden
committed
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
U32 unsatisfied_mask = (required_mask & ~data_mask);
U32 i = 0;
while (i < 15)
{
switch ((unsatisfied_mask & (1 << i)))
{
case MAP_VERTEX: llinfos << "Missing vert pos" << llendl; break;
case MAP_NORMAL: llinfos << "Missing normals" << llendl; break;
case MAP_TEXCOORD0: llinfos << "Missing TC 0" << llendl; break;
case MAP_TEXCOORD1: llinfos << "Missing TC 1" << llendl; break;
case MAP_TEXCOORD2: llinfos << "Missing TC 2" << llendl; break;
case MAP_TEXCOORD3: llinfos << "Missing TC 3" << llendl; break;
case MAP_COLOR: llinfos << "Missing vert color" << llendl; break;
case MAP_EMISSIVE: llinfos << "Missing emissive" << llendl; break;
case MAP_TANGENT: llinfos << "Missing tangent" << llendl; break;
case MAP_WEIGHT: llinfos << "Missing weight" << llendl; break;
case MAP_WEIGHT4: llinfos << "Missing weightx4" << llendl; break;
case MAP_CLOTHWEIGHT: llinfos << "Missing clothweight" << llendl; break;
case MAP_TEXTURE_INDEX: llinfos << "Missing tex index" << llendl; break;
default: llinfos << "Missing who effin knows" << llendl;
}
}
llerrs << "Shader consumption mismatches data provision." << llendl;
David Parks
committed
}
}
}
if (useVBOs())
{
David Parks
committed
if (mGLArray)
{
David Parks
committed
bindGLArray();
Leslie Linden
committed
setup = false; //do NOT perform pointer setup if using VAO
}
David Parks
committed
else
Leslie Linden
committed
const bool bindBuffer = bindGLBuffer();
const bool bindIndices = bindGLIndices();
setup = setup || bindBuffer || bindIndices;
David Parks
committed
if (gDebugGL && !mGLArray)
{
GLint buff;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if (gDebugSession)
{
gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
}
else
{
llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
}
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLIndices)
if (gDebugSession)
{
gFailLog << "Invalid GL index buffer bound: " << buff << std::endl;
}
else
{
llerrs << "Invalid GL index buffer bound: " << buff << llendl;
}
David Parks
committed
}
else
{
if (sGLRenderArray)
{
David Parks
committed
glBindVertexArray(0);
David Parks
committed
sGLRenderArray = 0;
David Parks
committed
sGLRenderIndices = 0;
}
if (mGLBuffer)
{
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
sBindCount++;
Leslie Linden
committed
setup = true; // ... or a VBO is deactivated
}
if (sGLRenderBuffer != mGLBuffer)
{
David Parks
committed
sGLRenderBuffer = mGLBuffer;
Leslie Linden
committed
setup = true; // ... or a client memory pointer changed
David Parks
committed
if (mGLIndices)
David Parks
committed
if (sIBOActive)
{
David Parks
committed
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
sBindCount++;
David Parks
committed
}
sGLRenderIndices = mGLIndices;
David Parks
committed
if (!mGLArray)
setupClientArrays(data_mask);
David Parks
committed
if (mGLBuffer)
{
if (data_mask && setup)
{
setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
sSetCount++;
}
}
}
// virtual (default)
David Parks
committed
void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
{
stop_glerror();
volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
if (gDebugGL && ((data_mask & mTypeMask) != data_mask))
for (U32 i = 0; i < LLVertexBuffer::TYPE_MAX; ++i)
{
U32 mask = 1 << i;
if (mask & data_mask && !(mask & mTypeMask))
{ //bit set in data_mask, but not set in mTypeMask
llwarns << "Missing required component " << vb_type_name[i] << llendl;
}
}
llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
David Parks
committed
if (LLGLSLShader::sNoFixedFunction)
David Parks
committed
if (data_mask & MAP_NORMAL)
David Parks
committed
S32 loc = TYPE_NORMAL;
void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
David Parks
committed
glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
David Parks
committed
if (data_mask & MAP_TEXCOORD3)
David Parks
committed
S32 loc = TYPE_TEXCOORD3;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
David Parks
committed
glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
David Parks
committed
if (data_mask & MAP_TEXCOORD2)
David Parks
committed
S32 loc = TYPE_TEXCOORD2;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
David Parks
committed
glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
David Parks
committed
if (data_mask & MAP_TEXCOORD1)
David Parks
committed
S32 loc = TYPE_TEXCOORD1;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
David Parks
committed
glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
David Parks
committed
if (data_mask & MAP_TANGENT)
David Parks
committed
S32 loc = TYPE_TANGENT;
void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]);
glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr);
David Parks
committed
if (data_mask & MAP_TEXCOORD0)
David Parks
committed
S32 loc = TYPE_TEXCOORD0;
void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
David Parks
committed
glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
David Parks
committed
if (data_mask & MAP_COLOR)
David Parks
committed
S32 loc = TYPE_COLOR;
void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
David Parks
committed
if (data_mask & MAP_EMISSIVE)
David Parks
committed
S32 loc = TYPE_EMISSIVE;
void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
David Parks
committed
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
David Parks
committed
if (data_mask & MAP_WEIGHT)
David Parks
committed
S32 loc = TYPE_WEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
Leslie Linden
committed
glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
David Parks
committed
if (data_mask & MAP_WEIGHT4)
David Parks
committed
S32 loc = TYPE_WEIGHT4;
void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
Leslie Linden
committed
glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
David Parks
committed
if (data_mask & MAP_CLOTHWEIGHT)
David Parks
committed
S32 loc = TYPE_CLOTHWEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
Leslie Linden
committed
glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
David Parks
committed
if (data_mask & MAP_TEXTURE_INDEX &&
(gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later
S32 loc = TYPE_TEXTURE_INDEX;
David Parks
committed
void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
David Parks
committed
glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
David Parks
committed
if (data_mask & MAP_VERTEX)
{
S32 loc = TYPE_VERTEX;
void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
David Parks
committed
}
}
else
David Parks
committed
if (data_mask & MAP_NORMAL)
David Parks
committed
glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL]));
David Parks
committed
if (data_mask & MAP_TEXCOORD3)
{
David Parks
committed
glClientActiveTextureARB(GL_TEXTURE3_ARB);
glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3]));
glClientActiveTextureARB(GL_TEXTURE0_ARB);
David Parks
committed
if (data_mask & MAP_TEXCOORD2)
David Parks
committed
{
David Parks
committed
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2]));
glClientActiveTextureARB(GL_TEXTURE0_ARB);
David Parks
committed
}
David Parks
committed
if (data_mask & MAP_TEXCOORD1)
David Parks
committed
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1]));
glClientActiveTextureARB(GL_TEXTURE0_ARB);
David Parks
committed
if (data_mask & MAP_TANGENT)
{
David Parks
committed
glClientActiveTextureARB(GL_TEXTURE2_ARB);
David Parks
committed
glTexCoordPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TANGENT], (void*)(base + mOffsets[TYPE_TANGENT]));
David Parks
committed
glClientActiveTextureARB(GL_TEXTURE0_ARB);
David Parks
committed
if (data_mask & MAP_TEXCOORD0)
David Parks
committed
{
David Parks
committed
glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0]));
David Parks
committed
}
David Parks
committed
if (data_mask & MAP_COLOR)
David Parks
committed
{
David Parks
committed
glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR]));
David Parks
committed
if (data_mask & MAP_VERTEX)
David Parks
committed
glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
}
}
llglassertok();
}
LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count)
: mType(type), mIndex(index), mCount(count)
{
llassert(mType == LLVertexBuffer::TYPE_INDEX ||
mType < LLVertexBuffer::TYPE_TEXTURE_INDEX);
}