diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index daeb58b279bb542f963e860774224c3989f2e31c..685334555a454c8a51e32ae809a68d53474c3edd 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1821,7 +1821,7 @@ void LLRender::flush()
 			mBuffer->getColorStrider(mColorsp, 0, count);
 		}
 		
-		//only flush the part of the 
+		mBuffer->flush();
 		mBuffer->setBuffer(immediate_mask);
 
 		if (mMode == LLRender::QUADS && sGLCoreProfile)
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 40a96eb407bdf313ddd331e4ba63749f242b66d4..a48669a30077daa7265358518b38514d78fe5843 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -150,19 +150,18 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
 
 
 //static
-void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
+void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& sLastMask)
 {
 	/*if (LLGLImmediate::sStarted)
 	{
 		llerrs << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl;
 	}*/
 
-	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
-
-	if (ref_mask != data_mask)
+	if (sLastMask != data_mask)
 	{
-		llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL);
-		
+
+		LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+
 		U32 mask[] =
 		{
 			MAP_VERTEX,
@@ -174,6 +173,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 			MAP_WEIGHT4,
 			MAP_BINORMAL,
 			MAP_CLOTHWEIGHT,
+			MAP_TEXTURE_INDEX,
 		};
 		
 		U32 type[] =
@@ -187,6 +187,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 			TYPE_WEIGHT4,
 			TYPE_BINORMAL,
 			TYPE_CLOTHWEIGHT,
+			TYPE_TEXTURE_INDEX-1,
 		};
 
 		GLenum array[] =
@@ -200,18 +201,20 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 			0,
 			0,
 			0,
+			0,
 		};
 
 		BOOL error = FALSE;
-		for (U32 i = 0; i < 9; ++i)
+		for (U32 i = 0; i < 10; ++i)
 		{
 			S32 loc = -1;
-			if (shader)
+
+			if (LLGLSLShader::sNoFixedFunction)
 			{
-				loc = shader->getAttribLocation(type[i]);
+				loc = type[i];
 			}
-
-			if (ref_mask & mask[i])
+									
+			if (sLastMask & mask[i])
 			{ //was enabled
 				if (!(data_mask & mask[i]))
 				{ //needs to be disabled
@@ -219,12 +222,12 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 					{
 						glDisableVertexAttribArrayARB(loc);
 					}
-					else if (!shader)
+					else
 					{
 						glDisableClientState(array[i]);
 					}
 				}
-				else if (gDebugGL && !shader && array[i])
+				else if (gDebugGL && !LLGLSLShader::sNoFixedFunction && array[i])
 				{ //needs to be enabled, make sure it was (DEBUG)
 					if (loc < 0 && !glIsEnabled(array[i]))
 					{
@@ -248,12 +251,12 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 					{
 						glEnableVertexAttribArrayARB(loc);
 					}
-					else if (!shader)
+					else
 					{
 						glEnableClientState(array[i]);
 					}
 				}
-				else if (!shader && array[i] && gDebugGL && glIsEnabled(array[i]))
+				else if (!LLGLSLShader::sNoFixedFunction && array[i] && gDebugGL && glIsEnabled(array[i]))
 				{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
 					if (gDebugSession)
 					{
@@ -290,12 +293,13 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 		for (U32 i = 0; i < 3; i++)
 		{
 			S32 loc = -1;
-			if (shader)
+
+			if (LLGLSLShader::sNoFixedFunction)
 			{
-				loc = shader->getAttribLocation(type_tc[i]);
+				loc = type_tc[i];
 			}
 
-			if (ref_mask & map_tc[i])
+			if (sLastMask & map_tc[i])
 			{
 				if (!(data_mask & map_tc[i]))
 				{ //disable
@@ -303,7 +307,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 					{
 						glDisableVertexAttribArrayARB(loc);
 					}
-					else if (!shader)
+					else
 					{
 						glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
 						glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -317,7 +321,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 				{
 					glEnableVertexAttribArrayARB(loc);
 				}
-				else if (!shader)
+				else
 				{
 					glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
 					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -326,9 +330,9 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 			}
 		}
 
-		if (!shader)
+		if (!LLGLSLShader::sNoFixedFunction)
 		{
-			if (ref_mask & MAP_BINORMAL)
+			if (sLastMask & MAP_BINORMAL)
 			{
 				if (!(data_mask & MAP_BINORMAL))
 				{
@@ -345,7 +349,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)
 			}
 		}
 		
-		ref_mask = data_mask;
+		sLastMask = data_mask;
 	}
 }
 
@@ -367,12 +371,12 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con
 
 	if (shader)
 	{
-		S32 loc = shader->getAttribLocation(LLVertexBuffer::TYPE_VERTEX);
+		S32 loc = LLVertexBuffer::TYPE_VERTEX;
 		if (loc > -1)
 		{
 			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV);
 		}
-		loc = shader->getAttribLocation(LLVertexBuffer::TYPE_NORMAL);
+		loc = LLVertexBuffer::TYPE_NORMAL;
 		if (loc > -1)
 		{
 			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV);
@@ -404,23 +408,15 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
 	
 	setupClientArrays(mask);
 
-	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
-
-	if (shader)
+	if (LLGLSLShader::sNoFixedFunction)
 	{
-		S32 loc = shader->getAttribLocation(LLVertexBuffer::TYPE_VERTEX);
-		if (loc > -1)
-		{
-			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos);
+		S32 loc = LLVertexBuffer::TYPE_VERTEX;
+		glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos);
 
-			if (tc)
-			{
-				loc = shader->getAttribLocation(LLVertexBuffer::TYPE_TEXCOORD0);
-				if (loc > -1)
-				{
-					glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc);
-				}
-			}
+		if (tc)
+		{
+			loc = LLVertexBuffer::TYPE_TEXCOORD0;
+			glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc);
 		}
 	}
 	else
@@ -470,14 +466,35 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
 	llassert(mRequestedNumVerts >= 0);
 	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 
-	if (mGLIndices != sGLRenderIndices)
+	if (mGLArray)
 	{
-		llerrs << "Wrong index buffer bound." << llendl;
+		if (mGLArray != sGLRenderArray)
+		{
+			llerrs << "Wrong vertex array bound." << llendl;
+		}
 	}
+	else
+	{
+		if (mGLIndices != sGLRenderIndices)
+		{
+			llerrs << "Wrong index buffer bound." << llendl;
+		}
 
-	if (mGLBuffer != sGLRenderBuffer)
+		if (mGLBuffer != sGLRenderBuffer)
+		{
+			llerrs << "Wrong vertex buffer bound." << llendl;
+		}
+	}
+
+	if (gDebugGL && useVBOs())
 	{
-		llerrs << "Wrong vertex buffer bound." << llendl;
+		GLint elem = 0;
+		glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
+
+		if (elem != mGLIndices)
+		{
+			llerrs << "Wrong index buffer bound!" << llendl;
+		}
 	}
 
 	if (mode >= LLRender::NUM_MODES)
@@ -508,14 +525,24 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
 		llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
 	}
 
-	if (mGLIndices != sGLRenderIndices)
+	if (mGLArray)
 	{
-		llerrs << "Wrong index buffer bound." << llendl;
+		if (mGLArray != sGLRenderArray)
+		{
+			llerrs << "Wrong vertex array bound." << llendl;
+		}
 	}
-
-	if (mGLBuffer != sGLRenderBuffer)
+	else
 	{
-		llerrs << "Wrong vertex buffer bound." << llendl;
+		if (mGLIndices != sGLRenderIndices)
+		{
+			llerrs << "Wrong index buffer bound." << llendl;
+		}
+
+		if (mGLBuffer != sGLRenderBuffer)
+		{
+			llerrs << "Wrong vertex buffer bound." << llendl;
+		}
 	}
 
 	if (mode >= LLRender::NUM_MODES)
@@ -544,9 +571,19 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 		llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
 	}
 
-	if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
+	if (mGLArray)
 	{
-		llerrs << "Wrong vertex buffer bound." << llendl;
+		if (mGLArray != sGLRenderArray)
+		{
+			llerrs << "Wrong vertex array bound." << llendl;
+		}
+	}
+	else
+	{
+		if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
+		{
+			llerrs << "Wrong vertex buffer bound." << llendl;
+		}
 	}
 
 	if (mode >= LLRender::NUM_MODES)
@@ -645,7 +682,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 	mUsage(usage),
 	mGLBuffer(0),
 	mGLArray(0),
-	mLastMask(0),
 	mGLIndices(0), 
 	mMappedData(NULL),
 	mMappedIndexData(NULL), 
@@ -686,12 +722,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 		mOffsets[i] = 0;
 	}
 
-	//initialize cached attrib pointers
-	for (U32 i = 0; i < LL_MAX_VERTEX_ATTRIB_LOCATION; i++)
-	{
-		mLastPointer[i] = (void*) 0xFFFFFFFF;
-	}
-
 	mTypeMask = typemask;
 	mSize = 0;
 	mAlignedOffset = 0;
@@ -1065,15 +1095,98 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
 		createGLBuffer();
 		createGLIndices();
 
+
 		if (gGLManager.mHasVertexArrayObject && useVBOs() && LLRender::sGLCoreProfile)
 		{
 			glGenVertexArrays(1, &mGLArray);
+			setupVertexArray();
 		}
 	}
 	
 	sAllocatedBytes += getSize() + getIndicesSize();
 }
 
+void LLVertexBuffer::setupVertexArray()
+{
+	bindGLArray();
+
+	U32 attrib_size[] = 
+	{
+		3, //TYPE_VERTEX,
+		3, //TYPE_NORMAL,
+		2, //TYPE_TEXCOORD0,
+		2, //TYPE_TEXCOORD1,
+		2, //TYPE_TEXCOORD2,
+		2, //TYPE_TEXCOORD3,
+		4, //TYPE_COLOR,
+		1, //TYPE_EMISSIVE,
+		3, //TYPE_BINORMAL,
+		1, //TYPE_WEIGHT,
+		4, //TYPE_WEIGHT4,
+		4, //TYPE_CLOTHWEIGHT,
+	};
+
+	U32 attrib_type[] =
+	{
+		GL_FLOAT, //TYPE_VERTEX,
+		GL_FLOAT, //TYPE_NORMAL,
+		GL_FLOAT, //TYPE_TEXCOORD0,
+		GL_FLOAT, //TYPE_TEXCOORD1,
+		GL_FLOAT, //TYPE_TEXCOORD2,
+		GL_FLOAT, //TYPE_TEXCOORD3,
+		GL_UNSIGNED_BYTE, //TYPE_COLOR,
+		GL_UNSIGNED_BYTE, //TYPE_EMISSIVE,
+		GL_FLOAT,   //TYPE_BINORMAL,
+		GL_FLOAT, //TYPE_WEIGHT,
+		GL_FLOAT, //TYPE_WEIGHT4,
+		GL_FLOAT, //TYPE_CLOTHWEIGHT,
+	};
+
+	U32 attrib_normalized[] =
+	{
+		GL_FALSE, //TYPE_VERTEX,
+		GL_FALSE, //TYPE_NORMAL,
+		GL_FALSE, //TYPE_TEXCOORD0,
+		GL_FALSE, //TYPE_TEXCOORD1,
+		GL_FALSE, //TYPE_TEXCOORD2,
+		GL_FALSE, //TYPE_TEXCOORD3,
+		GL_TRUE, //TYPE_COLOR,
+		GL_TRUE, //TYPE_EMISSIVE,
+		GL_FALSE,   //TYPE_BINORMAL,
+		GL_FALSE, //TYPE_WEIGHT,
+		GL_FALSE, //TYPE_WEIGHT4,
+		GL_FALSE, //TYPE_CLOTHWEIGHT,
+	};
+
+	bindGLBuffer(true);
+	bindGLIndices(true);
+
+	for (U32 i = 0; i < TYPE_MAX; ++i)
+	{
+		if (mTypeMask & (1 << i))
+		{
+			glEnableVertexAttribArrayARB(i);
+			glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); 
+		}
+		else
+		{
+			glDisableVertexAttribArrayARB(i);
+		}
+	}
+
+	if (mTypeMask & MAP_VERTEX)
+	{ //special handling for texture index
+		S32 loc = TYPE_TEXTURE_INDEX-1;
+		glEnableVertexAttribArrayARB(loc);
+		glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, sTypeSize[TYPE_VERTEX], (void*) (mOffsets[TYPE_VERTEX]+12));
+	}
+	else
+	{
+		glDisableVertexAttribArrayARB(TYPE_TEXTURE_INDEX-1);
+	}
+	glBindVertexArray(0);
+}
+
 void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
 {
 	llassert(newnverts >= 0);
@@ -1149,8 +1262,13 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
 
 	if (mResized && useVBOs())
 	{
-		freeClientBuffer() ;
-		setBuffer(0);
+		freeClientBuffer();
+		flush();
+
+		if (mGLArray)
+		{ //if size changed, offsets changed
+			setupVertexArray();
+		}
 	}
 }
 
@@ -1215,6 +1333,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
 // Map for data access
 U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
 {
+	bindGLBuffer(true);
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
 	if (mFinal)
 	{
@@ -1265,7 +1384,6 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 		if (!mVertexLocked)
 		{
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
-			setBuffer(0, type);
 			mVertexLocked = TRUE;
 			sMappedCount++;
 			stop_glerror();	
@@ -1380,6 +1498,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
+	bindGLIndices(true);
 	if (mFinal)
 	{
 		llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl;
@@ -1427,11 +1546,21 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 		{
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
 
-			setBuffer(0, TYPE_INDEX);
 			mIndexLocked = TRUE;
 			sMappedCount++;
 			stop_glerror();	
 
+			if (gDebugGL && useVBOs())
+			{
+				GLint elem = 0;
+				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
+
+				if (elem != mGLIndices)
+				{
+					llerrs << "Wrong index buffer bound!" << llendl;
+				}
+			}
+
 			if(sDisableVBOMapping)
 			{
 				map_range = false;
@@ -1528,19 +1657,20 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 	}
 }
 
-void LLVertexBuffer::unmapBuffer(S32 type)
+void LLVertexBuffer::unmapBuffer()
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
-	if (!useVBOs() || type == -2)
+	if (!useVBOs())
 	{
 		return ; //nothing to unmap
 	}
 
 	bool updated_all = false ;
 
-	if (mMappedData && mVertexLocked && type != TYPE_INDEX)
+	if (mMappedData && mVertexLocked)
 	{
-		updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating
+		bindGLBuffer(true);
+		updated_all = mIndexLocked; //both vertex and index buffers done updating
 
 		if(sDisableVBOMapping)
 		{
@@ -1604,8 +1734,9 @@ void LLVertexBuffer::unmapBuffer(S32 type)
 		sMappedCount--;
 	}
 	
-	if (mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
+	if (mMappedIndexData && mIndexLocked)
 	{
+		bindGLIndices();
 		if(sDisableVBOMapping)
 		{
 			if (!mMappedIndexRegions.empty())
@@ -1785,16 +1916,131 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 in
 
 //----------------------------------------------------------------------------
 
+bool LLVertexBuffer::bindGLArray()
+{
+	if (mGLArray && sGLRenderArray != mGLArray)
+	{
+		glBindVertexArray(mGLArray);
+		sGLRenderArray = mGLArray;
+		return true;
+	}
+		
+	return false;
+}
+
+bool LLVertexBuffer::bindGLBuffer(bool force_bind)
+{
+	bindGLArray();
+
+	bool ret = false;
+
+	if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
+	{
+		/*if (sMapped)
+		{
+			llerrs << "VBO bound while another VBO mapped!" << llendl;
+		}*/
+		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
+		sGLRenderBuffer = mGLBuffer;
+		sBindCount++;
+		sVBOActive = TRUE;
+
+		if (mGLArray)
+		{
+			llassert(sGLRenderArray == mGLArray);
+			//mCachedRenderBuffer = mGLBuffer;
+		}
+
+		ret = true;
+	}
+
+	if (gDebugGL && useVBOs())
+	{
+		GLint elem = 0;
+		glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &elem);
+
+		if (elem != mGLBuffer)
+		{
+			llerrs << "Wrong vertex buffer bound!" << llendl;
+		}
+	}
+
+	return ret;
+}
+
+bool LLVertexBuffer::bindGLIndices(bool force_bind)
+{
+	bindGLArray();
+
+	bool ret = false;
+	if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))))
+	{
+		/*if (sMapped)
+		{
+			llerrs << "VBO bound while another VBO mapped!" << llendl;
+		}*/
+		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
+		sGLRenderIndices = mGLIndices;
+		stop_glerror();
+		sBindCount++;
+		sIBOActive = TRUE;
+		ret = true;
+	}
+
+	if (gDebugGL && useVBOs())
+	{
+		GLint elem = 0;
+		glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
+
+		if (elem != mGLIndices)
+		{
+			llerrs << "Wrong index buffer bound!" << llendl;
+		}
+	}
+
+	return ret;
+}
+
+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();
+	}
+}
+
 // Set for rendering
-void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)
+void LLVertexBuffer::setBuffer(U32 data_mask)
 {
+	flush();
+
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
 	//set up pointers if the data mask is different ...
-	U32& ref_mask = mGLArray ? mLastMask : sLastMask;
-	BOOL setup = (ref_mask != data_mask);
+	BOOL setup = (sLastMask != data_mask);
 
 	if (gDebugGL && data_mask != 0)
-	{
+	{ //make sure data requirements are fulfilled
 		LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 		if (shader)
 		{
@@ -1823,37 +2069,25 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)
 
 	if (useVBOs())
 	{
-		if (mGLArray && mGLArray != sGLRenderArray)
+		if (mGLArray)
 		{
-			glBindVertexArray(mGLArray);
-			sGLRenderArray = mGLArray;
+			bindGLArray();
+			setup = FALSE; //do NOT perform pointer setup if using VAO
 		}
-
-		if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))
+		else
 		{
-			/*if (sMapped)
+			if (bindGLBuffer())
 			{
-				llerrs << "VBO bound while another VBO mapped!" << llendl;
-			}*/
-			glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
-			sBindCount++;
-			sVBOActive = TRUE;
-			setup = TRUE; // ... or the bound buffer changed
-		}
-		if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))
-		{
-			/*if (sMapped)
+				setup = TRUE;
+			}
+			if (bindGLIndices())
 			{
-				llerrs << "VBO bound while another VBO mapped!" << llendl;
-			}*/
-			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
-			stop_glerror();
-			sBindCount++;
-			sIBOActive = TRUE;
+				setup = TRUE;
+			}
 		}
 
 		BOOL error = FALSE;
-		if (gDebugGL)
+		if (gDebugGL && !mGLArray)
 		{
 			GLint buff;
 			glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
@@ -1888,81 +2122,16 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)
 			}
 		}
 
-		if (mResized)
+		
+	}
+	else
+	{	
+		if (sGLRenderArray)
 		{
-			if (gDebugGL)
-			{
-				GLint buff;
-				glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
-				if ((GLuint)buff != mGLBuffer)
-				{
-					if (gDebugSession)
-					{
-						error = TRUE;
-						gFailLog << "Invalid GL vertex buffer bound: " << std::endl;
-					}
-					else
-					{
-						llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
-					}
-				}
-
-				if (mGLIndices != 0)
-				{
-					glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
-					if ((GLuint)buff != mGLIndices)
-					{
-						if (gDebugSession)
-						{
-							error = TRUE;
-							gFailLog << "Invalid GL index buffer bound: "<< std::endl;
-						}
-						else
-						{
-							llerrs << "Invalid GL index buffer bound: " << buff << llendl;
-						}
-					}
-				}
-			}
-
-			if (mGLBuffer)
-			{
-				stop_glerror();
-				glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage);
-				stop_glerror();
-			}
-			if (mGLIndices)
-			{
-				stop_glerror();
-				glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage);
-				stop_glerror();
-			}
-
-			mEmpty = TRUE;
-			mResized = FALSE;
-
-			if (data_mask != 0)
-			{
-				if (gDebugSession)
-				{
-					error = TRUE;
-					gFailLog << "Buffer set for rendering before being filled after resize." << std::endl;
-				}
-				else
-				{
-					llerrs << "Buffer set for rendering before being filled after resize." << llendl;
-				}
-			}
+			glBindVertexArray(0);
+			sGLRenderArray = 0;
 		}
 
-		if (error)
-		{
-			ll_fail("LLVertexBuffer::mapBuffer failed");
-		}
-		unmapBuffer(type);
-	}
-	else
-	{		
 		if (mGLBuffer)
 		{
 			if (sVBOActive)
@@ -1974,30 +2143,30 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)
 			}
 			if (sGLRenderBuffer != mGLBuffer)
 			{
+				sGLRenderBuffer = mGLBuffer;
 				setup = TRUE; // ... or a client memory pointer changed
 			}
 		}
-		if (mGLIndices && sIBOActive)
+		if (mGLIndices)
 		{
-			/*if (sMapped)
+			if (sIBOActive)
 			{
-				llerrs << "VBO unbound while potentially mapped!" << llendl;
-			}*/
-			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-			sBindCount++;
-			sIBOActive = FALSE;
+				glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+				sBindCount++;
+				sIBOActive = FALSE;
+			}
+			
+			sGLRenderIndices = mGLIndices;
 		}
 	}
 
-	setupClientArrays(data_mask, ref_mask);
-		
-	if (mGLIndices)
+	if (!mGLArray)
 	{
-		sGLRenderIndices = mGLIndices;
+		setupClientArrays(data_mask, sLastMask);
 	}
+			
 	if (mGLBuffer)
 	{
-		sGLRenderBuffer = mGLBuffer;
 		if (data_mask && setup)
 		{
 			setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
@@ -2007,319 +2176,140 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)
 }
 
 // virtual (default)
-void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
+void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
 {
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER);
 	stop_glerror();
 	U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
 
-	if ((data_mask & mTypeMask) != data_mask)
+	/*if ((data_mask & mTypeMask) != data_mask)
 	{
 		llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
-	}
-
-	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
-
-	//assert that fixed function is allowed OR a shader is currently bound
-	llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL);
+	}*/
 
-	if (data_mask & MAP_NORMAL)
+	if (LLGLSLShader::sNoFixedFunction)
 	{
-		S32 loc = -1;
-		if (shader)
-		{
-			loc = shader->getAttribLocation(TYPE_NORMAL);
-		}
-		
-		if (loc >= 0)
+		if (data_mask & MAP_NORMAL)
 		{
+			S32 loc = TYPE_NORMAL;
 			void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
-		}
-		else if (!shader)
-		{
-			glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL]));
-		}
-	}
-	if (data_mask & MAP_TEXCOORD3)
-	{
-		S32 loc = -1;
-		if (shader)
-		{
-			loc = shader->getAttribLocation(TYPE_TEXCOORD3);
+			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
 		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_TEXCOORD3)
 		{
+			S32 loc = TYPE_TEXCOORD3;
 			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
-		}
-		else if (!shader)
-		{
-			glClientActiveTextureARB(GL_TEXTURE3_ARB);
-			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3]));
-			glClientActiveTextureARB(GL_TEXTURE0_ARB);
+			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
 		}
-	}
-	if (data_mask & MAP_TEXCOORD2)
-	{
-		S32 loc = -1;
-		if (shader)
-		{
-			loc = shader->getAttribLocation(TYPE_TEXCOORD2);
-		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_TEXCOORD2)
 		{
+			S32 loc = TYPE_TEXCOORD2;
 			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
-		}
-		else if (!shader)
-		{
-			glClientActiveTextureARB(GL_TEXTURE2_ARB);
-			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2]));
-			glClientActiveTextureARB(GL_TEXTURE0_ARB);
+			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
 		}
-	}
-	if (data_mask & MAP_TEXCOORD1)
-	{
-		S32 loc = -1;
-		if (shader)
-		{
-			loc = shader->getAttribLocation(TYPE_TEXCOORD1);
-		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_TEXCOORD1)
 		{
+			S32 loc = TYPE_TEXCOORD1;
 			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
-		}
-		else if (!shader)
-		{
-			glClientActiveTextureARB(GL_TEXTURE1_ARB);
-			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1]));
-			glClientActiveTextureARB(GL_TEXTURE0_ARB);
+			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
 		}
-	}
-	if (data_mask & MAP_BINORMAL)
-	{
-		S32 loc = -1;
-		if (shader)
-		{
-			loc = shader->getAttribLocation(TYPE_BINORMAL);
-		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_BINORMAL)
 		{
+			S32 loc = TYPE_BINORMAL;
 			void* ptr = (void*)(base + mOffsets[TYPE_BINORMAL]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
-		}
-		else if (!shader)
-		{
-			glClientActiveTextureARB(GL_TEXTURE2_ARB);
-			glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL]));
-			glClientActiveTextureARB(GL_TEXTURE0_ARB);
+			glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], ptr);
 		}
-	}
-	if (data_mask & MAP_TEXCOORD0)
-	{
-		S32 loc = -1;
-		if (shader)
-		{
-			loc = shader->getAttribLocation(TYPE_TEXCOORD0);
-		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_TEXCOORD0)
 		{
+			S32 loc = TYPE_TEXCOORD0;
 			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
+			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
 		}
-		else if (!shader)
+		if (data_mask & MAP_COLOR)
 		{
-			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0]));
+			S32 loc = TYPE_COLOR;
+			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
+			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
 		}
-	}
-	if (data_mask & MAP_COLOR)
-	{
-		S32 loc = -1;
-		if (shader)
+		if (data_mask & MAP_EMISSIVE)
 		{
-			loc = shader->getAttribLocation(TYPE_COLOR);
+			S32 loc = TYPE_EMISSIVE;
+			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
+			glVertexAttribPointerARB(loc, 1, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
 		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_WEIGHT)
 		{
-			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
+			S32 loc = TYPE_WEIGHT;
+			void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
+			glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
 		}
-		else if (!shader)
+		if (data_mask & MAP_WEIGHT4)
 		{
-			glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR]));
+			S32 loc = TYPE_WEIGHT4;
+			void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
+			glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
 		}
-	}
-	if (data_mask & MAP_EMISSIVE)
-	{
-		S32 loc = -1;
-		if (shader)
+		if (data_mask & MAP_CLOTHWEIGHT)
 		{
-			loc = shader->getAttribLocation(TYPE_EMISSIVE);
+			S32 loc = TYPE_CLOTHWEIGHT;
+			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
+			glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
 		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_TEXTURE_INDEX)
 		{
-			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc, 1, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
+			S32 loc = TYPE_TEXTURE_INDEX-1; //hack, texture index attrib location is off by one
+			void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
+			glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
 		}
-	}
-	if (data_mask & MAP_WEIGHT)
+		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], (void*)(base + 0));
+		}	
+	}	
+	else
 	{
-		S32 loc = -1;
-		if (shader)
+		if (data_mask & MAP_NORMAL)
 		{
-			loc = shader->getAttribLocation(TYPE_WEIGHT);
+			glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL]));
 		}
-
-		if (loc > -1)
+		if (data_mask & MAP_TEXCOORD3)
 		{
-			void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
+			glClientActiveTextureARB(GL_TEXTURE3_ARB);
+			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3]));
+			glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		}
-	}
-
-	if (data_mask & MAP_WEIGHT4)
-	{
-		if (shader)
+		if (data_mask & MAP_TEXCOORD2)
 		{
-			S32 loc = shader->getAttribLocation(TYPE_WEIGHT4);
-			if (loc > -1)
-			{
-				void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
-				if (mLastPointer[loc] != ptr)
-				{
-					glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
-				}
-				if (mGLArray)
-				{
-					mLastPointer[loc] = ptr;
-				}
-			}
+			glClientActiveTextureARB(GL_TEXTURE2_ARB);
+			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2]));
+			glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		}
-	}
-
-	if (data_mask & MAP_CLOTHWEIGHT)
-	{
-		S32 loc = -1;
-		if (shader)
+		if (data_mask & MAP_TEXCOORD1)
 		{
-			loc = shader->getAttribLocation(TYPE_CLOTHWEIGHT);
+			glClientActiveTextureARB(GL_TEXTURE1_ARB);
+			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1]));
+			glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		}
-
-		if (loc > -1)
+		if (data_mask & MAP_BINORMAL)
 		{
-			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
-			if (mLastPointer[loc] != ptr)
-			{
-				glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
-			}
-			if (mGLArray)
-			{
-				mLastPointer[loc] = ptr;
-			}
+			glClientActiveTextureARB(GL_TEXTURE2_ARB);
+			glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL]));
+			glClientActiveTextureARB(GL_TEXTURE0_ARB);
 		}
-	}
-	if (data_mask & MAP_VERTEX)
-	{
-		S32 loc = -1;
-		if (shader)
+		if (data_mask & MAP_TEXCOORD0)
 		{
-			loc = shader->getAttribLocation(TYPE_VERTEX);
+			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0]));
 		}
-
-		if (loc >= 0)
+		if (data_mask & MAP_COLOR)
 		{
-			if (data_mask & MAP_TEXTURE_INDEX)
-			{
-				glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
-			}
-			else
-			{
-				glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
-			}
+			glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR]));
 		}
-		else if (!shader)
+		if (data_mask & MAP_VERTEX)
 		{
-			if (data_mask & MAP_TEXTURE_INDEX)
-			{
-				glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
-			}
-			else
-			{
-				glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
-			}
-		}
+			glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+		}	
 	}
 
 	llglassertok();
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 60cfde39f58df750e0814578a8647c17cf574879..eba10dbaa5fcada10ef5155ac80057bccbbf9fb9 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -139,6 +139,7 @@ class LLVertexBuffer : public LLRefCount
 	// 3 - modify LLVertexBuffer::setupVertexBuffer
 	// 4 - modify LLVertexBuffer::setupClientArray
 	// 5 - modify LLViewerShaderMgr::mReservedAttribs
+	// 6 - update LLVertexBuffer::setupVertexArray
 	enum {
 		TYPE_VERTEX,
 		TYPE_NORMAL,
@@ -154,10 +155,9 @@ class LLVertexBuffer : public LLRefCount
 		TYPE_WEIGHT4,
 		TYPE_CLOTHWEIGHT,
 		TYPE_MAX,
-		TYPE_INDEX,
-		
 		//no actual additional data, but indicates position.w is texture index
 		TYPE_TEXTURE_INDEX,
+		TYPE_INDEX,		
 	};
 	enum {
 		MAP_VERTEX = (1<<TYPE_VERTEX),
@@ -181,10 +181,14 @@ class LLVertexBuffer : public LLRefCount
 
 	virtual ~LLVertexBuffer(); // use unref()
 
-	virtual void setupVertexBuffer(U32 data_mask) const; // pure virtual, called from mapBuffer()
+	virtual void setupVertexBuffer(U32 data_mask); // pure virtual, called from mapBuffer()
+	void setupVertexArray();
 	
 	void	genBuffer();
 	void	genIndices();
+	bool	bindGLBuffer(bool force_bind = false);
+	bool	bindGLIndices(bool force_bind = false);
+	bool	bindGLArray();
 	void	releaseBuffer();
 	void	releaseIndices();
 	void	createGLBuffer();
@@ -194,7 +198,7 @@ class LLVertexBuffer : public LLRefCount
 	void	updateNumVerts(S32 nverts);
 	void	updateNumIndices(S32 nindices); 
 	virtual BOOL	useVBOs() const;
-	void	unmapBuffer(S32 type);
+	void	unmapBuffer();
 	void freeClientBuffer() ;
 	void allocateClientVertexBuffer() ;
 	void allocateClientIndexBuffer() ;
@@ -207,7 +211,8 @@ class LLVertexBuffer : public LLRefCount
 	U8*		mapIndexBuffer(S32 index, S32 count, bool map_range);
 
 	// set for rendering
-	virtual void	setBuffer(U32 data_mask, S32 type = -1); 	// calls  setupVertexBuffer() if data_mask is not 0
+	virtual void	setBuffer(U32 data_mask); 	// calls  setupVertexBuffer() if data_mask is not 0
+	void flush(); //flush pending data to GL memory
 	// allocate buffer
 	void	allocateBuffer(S32 nverts, S32 nindices, bool create);
 	virtual void resizeBuffer(S32 newnverts, S32 newnindices);
@@ -273,9 +278,7 @@ class LLVertexBuffer : public LLRefCount
 	U32		mGLBuffer;		// GL VBO handle
 	U32		mGLIndices;		// GL IBO handle
 	U32		mGLArray;		// GL VAO handle
-	U32		mLastMask;		
-	mutable void*   mLastPointer[LL_MAX_VERTEX_ATTRIB_LOCATION];
-
+	
 	U8*		mMappedData;	// pointer to currently mapped data (NULL if unmapped)
 	U8*		mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped)
 	BOOL	mVertexLocked;			// if TRUE, vertex buffer is being or has been written to in client memory
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a8a7b165a3c10ff2103b40cb48459a2e5df03d59..32d4097ff36ea40ee5ea0681990a28f72c98549b 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7681,7 +7681,7 @@
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
-      <integer>1</integer>
+      <integer>0</integer>
     </map>
   <key>RenderDebugNormalScale</key>
   <map>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 9920caf7f667962699b5d5ace10bff2084660c29..74ee082bed280c00e8c1bfb248700e2a50d57f0f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -28,7 +28,8 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
@@ -97,7 +98,7 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz, 1.0);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 36000b86d66829b0fa6f3ab3046db3d4f4650039..908f3abcd0c5a673e522533183d2dd0ff6dbac2c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -27,7 +27,8 @@ uniform mat3 normal_matrix;
 uniform mat4 texture_matrix0;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec2 texcoord0;
@@ -43,7 +44,7 @@ void main()
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 	
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vary_normal = normalize(normal_matrix * normal);
 
 	vertex_color = diffuse_color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl
index b3558be67875247bbe9faf64e6aff4c36a729c8e..50e92c191b41ff43836d494f41ed408b4dd9e1ba 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl
@@ -27,7 +27,8 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE float emissive;
 ATTRIBUTE vec2 texcoord0;
 
@@ -48,7 +49,7 @@ void main()
 	//transform vertex
 	vec4 vert = vec4(position.xyz, 1.0);
 	vec4 pos = (modelview_matrix * vert);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index ef9f62da8470a28326275a20dc9cbb5072e943af..ab638991f7b4137382e4d1eaa5ea006af189d784 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -28,7 +28,8 @@ uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
 
@@ -49,7 +50,7 @@ void main()
 	//transform vertex
 	vec4 vert = vec4(position.xyz, 1.0);
 	vec4 pos = (modelview_matrix * vert);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl
index 0e05beac6780860e971b70a10466f0d606cc2062..77b0806bfcdf8311ff7e33f147da68fb31d7f706 100644
--- a/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl
@@ -27,7 +27,8 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE float emissive;
 ATTRIBUTE vec2 texcoord0;
 
@@ -42,7 +43,7 @@ VARYING float fog_depth;
 void main()
 {
 	//transform vertex
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
index 268e4127a2834fd1c1c643fa28a8b016f796a663..6a3777c7c8518baffbfd53b3f13f6d856c2eee6e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -28,7 +28,8 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
@@ -96,7 +97,7 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz, 1.0);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
index ef97e4f781f36f51b23d1ee75e72f7b5efb5a329..580ef2694fc5e9721d98b28892b13c856f66b930 100644
--- a/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
@@ -36,7 +36,8 @@ uniform vec4 origin;
 
 VARYING float vary_texture_index;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
@@ -50,7 +51,7 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz,1.0);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
index 2fd22cee9dac890364731865f567cd78204d792d..09dbd0b6cd8cb8f8d755a8f481144304797c7af4 100644
--- a/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
@@ -27,7 +27,8 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
  
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
@@ -44,7 +45,7 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz,1.0);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
diff --git a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
index 472ff219e5bb8c181cfa393b38e48ba0f68cdee1..86c592ea575de548315bbfa0088db5080b7d4501 100644
--- a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
@@ -29,7 +29,8 @@ uniform mat4 texture_matrix1;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
@@ -51,7 +52,7 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz,1.0);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 		
diff --git a/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
index 144336417e9187040f3282468cf084123f30e956..8e8f0664b05cd81ab2d818c50d211e6b3e665ad1 100644
--- a/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
@@ -28,7 +28,8 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec4 position;
+ATTRIBUTE vec3 position;
+ATTRIBUTE float texture_index;
 ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
@@ -45,7 +46,7 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz,1.0);
-	vary_texture_index = position.w;
+	vary_texture_index = texture_index;
 	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy;
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 7ae11bff94db57ea80b68b688ece608933d6fc3f..d36379b0e7546a756164113290fc43c37a837595 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1216,7 +1216,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 	
@@ -1441,7 +1441,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 			if (map_range)
 			{
-				mVertexBuffer->setBuffer(0);
+				mVertexBuffer->flush();
 			}
 		}
 		else
@@ -1588,7 +1588,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 			if (map_range)
 			{
-				mVertexBuffer->setBuffer(0);
+				mVertexBuffer->flush();
 			}
 
 			if (do_bump)
@@ -1625,7 +1625,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 				if (map_range)
 				{
-					mVertexBuffer->setBuffer(0);
+					mVertexBuffer->flush();
 				}
 			}
 		}
@@ -1675,7 +1675,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 		
@@ -1695,7 +1695,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 		
@@ -1715,7 +1715,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 	
@@ -1727,7 +1727,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 
@@ -1757,7 +1757,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 
@@ -1796,7 +1796,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 		if (map_range)
 		{
-			mVertexBuffer->setBuffer(0);
+			mVertexBuffer->flush();
 		}
 	}
 	if (rebuild_tcoord)
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index db5e4a2fb5ccb9344985630f9740d66d703df6ad..cc92ab453900209739c6009b2717ba8aaa9a5fe8 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -320,7 +320,7 @@ void LLSpatialGroup::buildOcclusion()
 	}
 	
 	{
-		mOcclusionVerts->setBuffer(0);
+		mOcclusionVerts->flush();
 	}
 
 	clearState(LLSpatialGroup::OCCLUSION_DIRTY);
diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp
index 4bde2dfcab55160ec92b88633588ae6dec55c6f5..c3eb70f850c2a7622d5a2423b7e32908a2a850a9 100644
--- a/indra/newview/llsprite.cpp
+++ b/indra/newview/llsprite.cpp
@@ -243,7 +243,7 @@ void LLSprite::updateFace(LLFace &face)
 		*indicesp++ = 3 + index_offset;
 	}
 
-	face.getVertexBuffer()->setBuffer(0);
+	face.getVertexBuffer()->flush();
 	face.mCenterAgent = mPosition;
 }
 
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 59835028a17888fc123d317ee871e6ca60983a31..331eb8b8f4a9ca876583084a9c88a7c21a3e488b 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -817,7 +817,7 @@ void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
 		}
 	}
 
-	buffer->setBuffer(0);
+	buffer->flush();
 }
 
 const U32 UPDATE_GEOMETRY_CALL_MASK			= 0x1FFF; // 8K samples before overflow
diff --git a/indra/newview/llviewerjointmesh_sse.cpp b/indra/newview/llviewerjointmesh_sse.cpp
index 400b49d04602a58cba668a69362d5dc3cb9c1da1..00ed47e091b129da929e5bf82fb62ee1fc9e2092 100644
--- a/indra/newview/llviewerjointmesh_sse.cpp
+++ b/indra/newview/llviewerjointmesh_sse.cpp
@@ -101,7 +101,7 @@ void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh)
 		((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]);
 	}
 
-	buffer->setBuffer(0);
+	buffer->flush();
 }
 
 #else
diff --git a/indra/newview/llviewerjointmesh_vec.cpp b/indra/newview/llviewerjointmesh_vec.cpp
index 6600d01d171072cc52b5b8b626cae8f2d35f2036..a8713b6f0580bb506346868504f9371303ddc256 100644
--- a/indra/newview/llviewerjointmesh_vec.cpp
+++ b/indra/newview/llviewerjointmesh_vec.cpp
@@ -92,6 +92,6 @@ void LLViewerJointMesh::updateGeometryVectorized(LLFace *face, LLPolyMesh *mesh)
 		((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]);
 	}
 
-	buffer->setBuffer(0);
+	buffer->flush();
 #endif
 }
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index d1d3334fed953506747e5fbdaceafd2837233e2e..b0d97ee5f631569366fed99350ea131b906f55d4 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -317,6 +317,7 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)
 		mReservedAttribs.push_back("weight");
 		mReservedAttribs.push_back("weight4");
 		mReservedAttribs.push_back("clothing");
+		mReservedAttribs.push_back("texture_index");
 
 		mAvatarUniforms.push_back("matrixPalette");
 		mAvatarUniforms.push_back("gWindDir");
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7c6a815defc53facb45602cf4473b5a1a366556c..2a670275a3080bcb13eac0086493c1c580f746bd 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2142,7 +2142,7 @@ void LLVOAvatar::updateMeshData()
 			}
 
 			stop_glerror();
-			buff->setBuffer(0);
+			buff->flush();
 
 			if(!f_num)
 			{
@@ -4132,7 +4132,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 			LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer();
 			if (vb)
 			{
-				vb->setBuffer(0);
+				vb->flush();
 			}
 		}
 	}
diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp
index ce256fdedf47371272a636bd6a931441f6f88b2b..0060f81ab5043f5235b6b1fd0ae03e868c9a515a 100644
--- a/indra/newview/llvoground.cpp
+++ b/indra/newview/llvoground.cpp
@@ -162,7 +162,7 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
 	*(texCoordsp++) = LLVector2(0.f, 1.f);
 	*(texCoordsp++) = LLVector2(0.5f, 0.5f);
 	
-	face->getVertexBuffer()->setBuffer(0);
+	face->getVertexBuffer()->flush();
 	LLPipeline::sCompiles++;
 	return TRUE;
 }
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index a4b0910c926c0abb839fcc7f4d097e43077cfccf..d7edc94c2f02985c5b7dee0bd8feb5ea817723dc 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -513,7 +513,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
 		}
 	}
 
-	buffer->setBuffer(0);
+	buffer->flush();
 	mFaceList.clear();
 }
 
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 29ca16ede614173d39bd727acbb3b8d042f41e42..d90c3be6c78efcf7b2f84ad40f46aed8537955ed 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -1267,7 +1267,7 @@ void LLVOSky::updateDummyVertexBuffer()
 	LLStrider<LLVector3> vertices ;
 	mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices,  0);
 	*vertices = mCameraPosAgent ;
-	mFace[FACE_DUMMY]->getVertexBuffer()->setBuffer(0) ;
+	mFace[FACE_DUMMY]->getVertexBuffer()->flush();
 }
 //----------------------------------
 //end of fake vertex buffer updating
@@ -1351,7 +1351,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 			*indicesp++ = index_offset + 3;
 			*indicesp++ = index_offset + 2;
 
-			buff->setBuffer(0);
+			buff->flush();
 		}
 	}
 
@@ -1516,7 +1516,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 	*indicesp++ = index_offset + 2;
 	*indicesp++ = index_offset + 3;
 
-	facep->getVertexBuffer()->setBuffer(0);
+	facep->getVertexBuffer()->flush();
 
 	if (is_sun)
 	{
@@ -2030,7 +2030,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 		}
 	}
 
-	face->getVertexBuffer()->setBuffer(0);
+	face->getVertexBuffer()->flush();
 }
 
 
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index 7e00350926b22970bf5aa2cf9ee11889665b8dea..bc82b0df130f6ea79a3cdadd6354815d82f2684d 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -57,7 +57,7 @@ class LLVertexBufferTerrain : public LLVertexBuffer
 	};
 
 	// virtual
-	void setupVertexBuffer(U32 data_mask) const
+	void setupVertexBuffer(U32 data_mask)
 	{	
 		if (LLGLSLShader::sNoFixedFunction)
 		{ //just use default if shaders are in play
@@ -1122,7 +1122,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
 		index_offset += facep->getGeomCount();
 	}
 
-	buffer->setBuffer(0);
+	buffer->flush();
 	mFaceList.clear();
 }
 
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 4cef0f5b5beb52e330b70c154f0df63410828a64..6486fd24ea4ba12682f91b2a09728038fde37413 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -858,7 +858,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 			slices /= 2; 
 		}
 
-		mReferenceBuffer->setBuffer(0);
+		mReferenceBuffer->flush();
 		llassert(vertex_count == max_vertices);
 		llassert(index_count == max_indices);
 	}
@@ -940,8 +940,8 @@ void LLVOTree::updateMesh()
 
 	genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
 	
-	mReferenceBuffer->setBuffer(0);
-	buff->setBuffer(0);
+	mReferenceBuffer->flush();
+	buff->flush();
 }
 
 void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices, 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 3b31100305a0bd192844a2d7c5031d0293bebc0d..c56a62a41b4a3837219619c7ea920683aec35dec 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4422,7 +4422,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 		
 		for (std::set<LLVertexBuffer*>::iterator iter = mapped_buffers.begin(); iter != mapped_buffers.end(); ++iter)
 		{
-			(*iter)->setBuffer(0);
+			(*iter)->flush();
 		}
 
 		// don't forget alpha
@@ -4430,7 +4430,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 		   !group->mVertexBuffer.isNull() && 
 		   group->mVertexBuffer->isLocked())
 		{
-			group->mVertexBuffer->setBuffer(0);
+			group->mVertexBuffer->flush();
 		}
 
 		//if not all buffers are unmapped
@@ -4446,7 +4446,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 					LLVertexBuffer* buff = face->getVertexBuffer();
 					if (face && buff && buff->isLocked())
 					{
-						buff->setBuffer(0) ;
+						buff->flush();
 					}
 				}
 			} 
@@ -4852,7 +4852,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			++face_iter;
 		}
 
-		buffer->setBuffer(0);
+		buffer->flush();
 	}
 
 	group->mBufferMap[mask].clear();
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index e70ac0a2e747600e753a26b59617e02cd6b0886a..75198c465be8535b35feeda15b7039ff2f240170 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -231,7 +231,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
 		}
 	}
 	
-	buff->setBuffer(0);
+	buff->flush();
 
 	mDrawable->movePartition();
 	LLPipeline::sCompiles++;
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 824cb8a15f04be252d2d6ae82e5fab28f07119c6..c26aefb28f7cba6732fef9f21cf3433c158db887 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -326,7 +326,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 
 		buildFanBuffer(vertices, texCoords, indices);
 
-		mFanVerts->setBuffer(0);
+		mFanVerts->flush();
 	}
 
 	{
@@ -388,7 +388,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 			buildStripsBuffer(begin_stack, end_stack,  vertices, texCoords, indices);
 
 			// and unlock the buffer
-			segment->setBuffer(0);
+			segment->flush();
 		}
 	}
 #else
@@ -468,7 +468,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 		}
 	}
 
-	mStripsVerts->setBuffer(0);
+	mStripsVerts->flush();
 #endif
 
 	updateStarColors();
@@ -826,6 +826,6 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
 		*(colorsp++)    = LLColor4U(mStarColors[vtx]);
 	}
 
-	mStarsVerts->setBuffer(0);
+	mStarsVerts->flush();
 	return TRUE;
 }
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 0fbe0308321eb0a9ef2aa402099f75abb3dcc8f1..28391bf423f2a11284d4ff7d07da252641e5126e 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6553,7 +6553,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		v[1] = LLVector3(-1,3,0);
 		v[2] = LLVector3(3,-1,0);
 				
-		buff->setBuffer(0);
+		buff->flush();
 
 		LLGLDisable blend(GL_BLEND);