From 71a660e0060b9aa2c5c01fd94e8070075b373d8d Mon Sep 17 00:00:00 2001
From: Leslie Linden <leslie@lindenlab.com>
Date: Thu, 26 Jan 2012 10:17:41 -0800
Subject: [PATCH] * Fixed up shader compilation errors to get lighting and
 shadows working again on Mac. * Cleaned up vertex buffer allocation to
 guarantee allocation and deallocation using the same allocation methods from
 the same pools. * Added new shader feature for atmospheric helpers in the
 absence of lighting.

Reviewed by davep.
---
 indra/llrender/llglslshader.cpp               |  21 +-
 indra/llrender/llglslshader.h                 |   1 +
 indra/llrender/llshadermgr.cpp                |   5 +-
 indra/llrender/llvertexbuffer.cpp             | 222 +++++++++---------
 indra/llrender/llvertexbuffer.h               |  31 ++-
 .../class1/deferred/alphaSkinnedV.glsl        |   6 +
 .../shaders/class1/deferred/alphaV.glsl       |   6 +
 .../shaders/class1/deferred/avatarAlphaV.glsl |   6 +
 .../class2/deferred/alphaSkinnedV.glsl        |   6 +
 .../shaders/class2/deferred/alphaV.glsl       |   6 +
 .../shaders/class2/deferred/avatarAlphaV.glsl |   6 +
 indra/newview/llviewershadermgr.cpp           |  31 ++-
 12 files changed, 211 insertions(+), 136 deletions(-)

diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 6b2852670a4..3773568ad88 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -64,10 +64,23 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
 }
 
 LLShaderFeatures::LLShaderFeatures()
-: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
-hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
-hasAlphaMask(false)
+	: atmosphericHelpers(false)
+	, calculatesLighting(false)
+	, calculatesAtmospherics(false)
+	, hasLighting(false)
+	, isAlphaLighting(false)
+	, isShiny(false)
+	, isFullbright(false)
+	, isSpecular(false)
+	, hasWaterFog(false)
+	, hasTransport(false)
+	, hasSkinning(false)
+	, hasObjectSkinning(false)
+	, hasAtmospherics(false)
+	, hasGamma(false)
+	, mIndexedTextureChannels(0)
+	, disableTextureIndex(false)
+	, hasAlphaMask(false)
 {
 }
 
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 00b4b0dbd40..7873fe3c4ee 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -33,6 +33,7 @@
 class LLShaderFeatures
 {
 public:
+	bool atmosphericHelpers;
 	bool calculatesLighting;
 	bool calculatesAtmospherics;
 	bool hasLighting; // implies no transport (it's possible to have neither though)
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 1a03aeebb7d..908443e8cf2 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -94,13 +94,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		}
 	}
 
-	if (features->calculatesLighting)
+	if (features->calculatesLighting || features->atmosphericHelpers)
 	{
 		if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))
 		{
 			return FALSE;
 		}
+	}
 		
+	if (features->calculatesLighting)
+	{
 		if (features->isSpecular)
 		{
 			if (!shader->attachObject("lighting/lightFuncSpecularV.glsl"))
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 518f3898a4a..90698853414 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -53,19 +53,19 @@ U32 nhpo2(U32 v)
 //============================================================================
 
 //static
-LLVBOPool LLVertexBuffer::sStreamVBOPool;
-LLVBOPool LLVertexBuffer::sDynamicVBOPool;
-LLVBOPool LLVertexBuffer::sStreamIBOPool;
-LLVBOPool LLVertexBuffer::sDynamicIBOPool;
+LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
+LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
+LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
+LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
 U32 LLVBOPool::sBytesPooled = 0;
 
-LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
+LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL;
 U32 LLVertexBuffer::sBindCount = 0;
 U32 LLVertexBuffer::sSetCount = 0;
 S32 LLVertexBuffer::sCount = 0;
 S32 LLVertexBuffer::sGLCount = 0;
 S32 LLVertexBuffer::sMappedCount = 0;
-BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
+BOOL LLVertexBuffer::sDisableVBOMapping = FALSE;
 BOOL LLVertexBuffer::sEnableVBOs = TRUE;
 U32 LLVertexBuffer::sGLRenderBuffer = 0;
 U32 LLVertexBuffer::sGLRenderArray = 0;
@@ -204,8 +204,8 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
 	Record rec;
 	rec.mGLName = name;
 	rec.mClientData = buffer;
-
-	if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB)
+	
+	if (buffer == NULL)
 	{
 		glDeleteBuffersARB(1, &rec.mGLName);
 	}
@@ -282,7 +282,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
 {
 	if (sLastMask != data_mask)
 	{
-		BOOL error = FALSE;
+		bool error = false;
 
 		if (LLGLSLShader::sNoFixedFunction)
 		{
@@ -343,7 +343,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
 						{
 							if (gDebugSession)
 							{
-								error = TRUE;
+								error = true;
 								gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
 							}
 							else
@@ -363,7 +363,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
 					{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
 						if (gDebugSession)
 						{
-							error = TRUE;
+							error = true;
 							gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
 						}
 						else
@@ -547,7 +547,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
 void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
 {
 	validateRange(start, end, count, indices_offset);
-	mMappable = FALSE;
+	mMappable = false;
 	gGL.syncMatrices();
 
 	llassert(mNumVerts >= 0);
@@ -602,7 +602,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(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
-	mMappable = FALSE;
+	mMappable = false;
 	gGL.syncMatrices();
 
 	llassert(mNumIndices >= 0);
@@ -648,7 +648,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
 void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 {
 	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
-	mMappable = FALSE;
+	mMappable = false;
 	gGL.syncMatrices();
 	
 	llassert(mNumVerts >= 0);
@@ -688,23 +688,13 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 //static
 void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
 {
-	sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
-	sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
+	sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
+	sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
 
-	if(!sPrivatePoolp)
+	if (!sPrivatePoolp)
 	{ 
-		sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ;
+		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 
@@ -757,65 +747,79 @@ void LLVertexBuffer::cleanupClass()
 
 //----------------------------------------------------------------------------
 
-LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
-	LLRefCount(),
-
-	mNumVerts(0),
-	mNumIndices(0),
-	mUsage(usage),
-	mGLBuffer(0),
-	mGLArray(0),
-	mGLIndices(0), 
-	mMappedData(NULL),
-	mMappedIndexData(NULL), 
-	mVertexLocked(FALSE),
-	mIndexLocked(FALSE),
-	mFinal(FALSE),
-	mEmpty(TRUE),
-	mFence(NULL)
+S32 LLVertexBuffer::determineUsage(S32 usage)
 {
-	LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
-	mFence = NULL;
+	S32 ret_usage = usage;
+
 	if (!sEnableVBOs)
 	{
-		mUsage = 0 ; 
+		ret_usage = 0;
 	}
-
-	if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
+	
+	if (usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
 	{
-		mUsage = 0;
+		ret_usage = 0;
 	}
 	
-	if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
+	if (usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
 	{
-		mUsage = GL_STREAM_DRAW_ARB;
+		ret_usage = GL_STREAM_DRAW_ARB;
 	}
-
-	if (mUsage == 0 && LLRender::sGLCoreProfile)
+	
+	if (usage == 0 && LLRender::sGLCoreProfile)
 	{ //MUST use VBOs for all rendering
-		mUsage = GL_STREAM_DRAW_ARB;
+		ret_usage = GL_STREAM_DRAW_ARB;
 	}
-
-	if (mUsage && mUsage != GL_STREAM_DRAW_ARB)
+	
+	if (usage && usage != GL_STREAM_DRAW_ARB)
 	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
 		if (sDisableVBOMapping)
 		{ //always use stream draw if VBO mapping is disabled
-			mUsage = GL_STREAM_DRAW_ARB;
+			ret_usage = GL_STREAM_DRAW_ARB;
 		}
 		else
 		{
-			mUsage = GL_DYNAMIC_DRAW_ARB;
+			ret_usage = GL_DYNAMIC_DRAW_ARB;
 		}
 	}
 	
+	return ret_usage;
+}
+
+LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
+	LLRefCount(),
+
+	mNumVerts(0),
+	mNumIndices(0),
+	mAlignedOffset(0),
+	mAlignedIndexOffset(0),
+	mSize(0),
+	mIndicesSize(0),
+	mTypeMask(typemask),
+	mUsage(LLVertexBuffer::determineUsage(usage)),
+	mGLBuffer(0),
+	mGLIndices(0),
+	mGLArray(0),
+	mMappedData(NULL),
+	mMappedIndexData(NULL),
+	mMappedDataUsingVBOs(false),
+	mMappedIndexDataUsingVBOs(false),
+	mVertexLocked(false),
+	mIndexLocked(false),
+	mFinal(false),
+	mEmpty(true),
+	mMappable(false),
+	mFence(NULL)
+{
+	LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
 
 	if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping)
 	{
-		mMappable = TRUE;
+		mMappable = true;
 	}
 	else
 	{
-		mMappable = FALSE;
+		mMappable = false;
 	}
 
 	//zero out offsets
@@ -824,12 +828,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 		mOffsets[i] = 0;
 	}
 
-	mTypeMask = typemask;
-	mSize = 0;
-	mIndicesSize = 0;
-	mAlignedOffset = 0;
-	mAlignedIndexOffset = 0;
-
 	sCount++;
 }
 
@@ -1010,9 +1008,11 @@ void LLVertexBuffer::createGLBuffer(U32 size)
 		return;
 	}
 
-	mEmpty = TRUE;
+	mEmpty = true;
 
-	if (useVBOs())
+	mMappedDataUsingVBOs = useVBOs();
+	
+	if (mMappedDataUsingVBOs)
 	{
 		genBuffer(size);
 	}
@@ -1039,12 +1039,14 @@ void LLVertexBuffer::createGLIndices(U32 size)
 		return;
 	}
 
-	mEmpty = TRUE;
+	mEmpty = true;
 
 	//pad by 16 bytes for aligned copies
 	size += 16;
 
-	if (useVBOs())
+	mMappedIndexDataUsingVBOs = useVBOs();
+
+	if (mMappedIndexDataUsingVBOs)
 	{
 		//pad by another 16 bytes for VBO pointer adjustment
 		size += 16;
@@ -1064,15 +1066,15 @@ void LLVertexBuffer::destroyGLBuffer()
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER);
 	if (mGLBuffer)
 	{
-		if (useVBOs())
+		if (mMappedDataUsingVBOs)
 		{
 			releaseBuffer();
 		}
 		else
 		{
-			FREE_MEM(sPrivatePoolp, (void*) mMappedData) ;
+			FREE_MEM(sPrivatePoolp, (void*) mMappedData);
 			mMappedData = NULL;
-			mEmpty = TRUE;
+			mEmpty = true;
 		}
 	}
 	
@@ -1085,15 +1087,15 @@ void LLVertexBuffer::destroyGLIndices()
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES);
 	if (mGLIndices)
 	{
-		if (useVBOs())
+		if (mMappedIndexDataUsingVBOs)
 		{
 			releaseIndices();
 		}
 		else
 		{
-			FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ;
+			FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData);
 			mMappedIndexData = NULL;
-			mEmpty = TRUE;
+			mEmpty = true;
 		}
 	}
 
@@ -1278,16 +1280,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
 	}
 }
 
-BOOL LLVertexBuffer::useVBOs() const
+bool LLVertexBuffer::useVBOs() const
 {
 	//it's generally ineffective to use VBO for things that are streaming on apple
-		
-	if (!mUsage)
-	{
-		return FALSE;
-	}
-
-	return TRUE;
+	return (mUsage != 0);
 }
 
 //----------------------------------------------------------------------------
@@ -1367,7 +1363,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 		if (!mVertexLocked)
 		{
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
-			mVertexLocked = TRUE;
+			mVertexLocked = true;
 			sMappedCount++;
 			stop_glerror();	
 
@@ -1446,8 +1442,8 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
 			{
 				log_glerror();
 
-			//check the availability of memory
-			LLMemory::logMemoryInfo(TRUE) ; 
+				//check the availability of memory
+				LLMemory::logMemoryInfo(TRUE) ; 
 			
 				if(mMappable)
 				{			
@@ -1546,7 +1542,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
 		{
 			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
 
-			mIndexLocked = TRUE;
+			mIndexLocked = true;
 			sMappedCount++;
 			stop_glerror();	
 
@@ -1741,7 +1737,7 @@ void LLVertexBuffer::unmapBuffer()
 			mMappedData = NULL;
 		}
 
-		mVertexLocked = FALSE ;
+		mVertexLocked = false;
 		sMappedCount--;
 	}
 	
@@ -1808,13 +1804,13 @@ void LLVertexBuffer::unmapBuffer()
 			mMappedIndexData = NULL ;
 		}
 
-		mIndexLocked = FALSE ;
+		mIndexLocked = false ;
 		sMappedCount--;
 	}
 
 	if(updated_all)
 	{
-		mEmpty = FALSE;
+		mEmpty = false;
 	}
 }
 
@@ -1834,12 +1830,12 @@ template <class T,S32 type> struct VertexBufferStrider
 			if (ptr == NULL)
 			{
 				llwarns << "mapIndexBuffer failed!" << llendl;
-				return FALSE;
+				return false;
 			}
 
 			strider = (T*)ptr;
 			strider.setStride(0);
-			return TRUE;
+			return true;
 		}
 		else if (vbo.hasDataType(type))
 		{
@@ -1850,18 +1846,18 @@ template <class T,S32 type> struct VertexBufferStrider
 			if (ptr == NULL)
 			{
 				llwarns << "mapVertexBuffer failed!" << llendl;
-				return FALSE;
+				return false;
 			}
 
 			strider = (T*)ptr;
 			strider.setStride(stride);
-			return TRUE;
+			return true;
 		}
 		else
 		{
 			llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
 		}
-		return FALSE;
+		return false;
 	}
 };
 
@@ -2014,7 +2010,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 
 	LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
 	//set up pointers if the data mask is different ...
-	BOOL setup = (sLastMask != data_mask);
+	bool setup = (sLastMask != data_mask);
 
 	if (gDebugGL && data_mask != 0)
 	{ //make sure data requirements are fulfilled
@@ -2048,21 +2044,17 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 		if (mGLArray)
 		{
 			bindGLArray();
-			setup = FALSE; //do NOT perform pointer setup if using VAO
+			setup = false; //do NOT perform pointer setup if using VAO
 		}
 		else
 		{
-			if (bindGLBuffer())
-			{
-				setup = TRUE;
-			}
-			if (bindGLIndices())
-			{
-				setup = TRUE;
-			}
+			const bool bindBuffer = bindGLBuffer();
+			const bool bindIndices = bindGLIndices();
+			
+			setup = setup || bindBuffer || bindIndices;
 		}
 
-		BOOL error = FALSE;
+		bool error = false;
 		if (gDebugGL && !mGLArray)
 		{
 			GLint buff;
@@ -2071,7 +2063,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 			{
 				if (gDebugSession)
 				{
-					error = TRUE;
+					error = true;
 					gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
 				}
 				else
@@ -2087,7 +2079,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 				{
 					if (gDebugSession)
 					{
-						error = TRUE;
+						error = true;
 						gFailLog << "Invalid GL index buffer bound: " << buff <<  std::endl;
 					}
 					else
@@ -2119,12 +2111,12 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 				glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
 				sBindCount++;
 				sVBOActive = FALSE;
-				setup = TRUE; // ... or a VBO is deactivated
+				setup = true; // ... or a VBO is deactivated
 			}
 			if (sGLRenderBuffer != mGLBuffer)
 			{
 				sGLRenderBuffer = mGLBuffer;
-				setup = TRUE; // ... or a client memory pointer changed
+				setup = true; // ... or a client memory pointer changed
 			}
 		}
 		if (mGLIndices)
@@ -2221,19 +2213,19 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
 		{
 			S32 loc = TYPE_WEIGHT;
 			void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
-			glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
+			glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
 		}
 		if (data_mask & MAP_WEIGHT4)
 		{
 			S32 loc = TYPE_WEIGHT4;
 			void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
-			glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
+			glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
 		}
 		if (data_mask & MAP_CLOTHWEIGHT)
 		{
 			S32 loc = TYPE_CLOTHWEIGHT;
 			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
-			glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
+			glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
 		}
 		if (data_mask & MAP_TEXTURE_INDEX)
 		{
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index e1cbfd3b619..a0d21b4a36c 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -55,9 +55,14 @@ class LLVBOPool
 {
 public:
 	static U32 sBytesPooled;
+	
+	LLVBOPool(U32 vboUsage, U32 vboType)
+		: mUsage(vboUsage)
+		, mType(vboType)
+	{}
 
-	U32 mUsage;
-	U32 mType;
+	const U32 mUsage;
+	const U32 mType;
 
 	//size MUST be a power of 2
 	volatile U8* allocate(U32& name, U32 size);
@@ -103,6 +108,7 @@ class LLVertexBuffer : public LLRefCount
 	};
 
 	LLVertexBuffer(const LLVertexBuffer& rhs)
+		: mUsage(rhs.mUsage)
 	{
 		*this = rhs;
 	}
@@ -201,7 +207,7 @@ class LLVertexBuffer : public LLRefCount
 	void 	destroyGLIndices();
 	void	updateNumVerts(S32 nverts);
 	void	updateNumIndices(S32 nindices); 
-	virtual BOOL	useVBOs() const;
+	bool	useVBOs() const;
 	void	unmapBuffer();
 		
 public:
@@ -274,18 +280,24 @@ class LLVertexBuffer : public LLRefCount
 	S32		mSize;
 	S32		mIndicesSize;
 	U32		mTypeMask;
-	S32		mUsage;			// GL usage
+
+	const S32		mUsage;			// GL usage
+	
 	U32		mGLBuffer;		// GL VBO handle
 	U32		mGLIndices;		// GL IBO handle
 	U32		mGLArray;		// GL VAO handle
 	
 	volatile U8* mMappedData;	// pointer to currently mapped data (NULL if unmapped)
 	volatile 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
-	BOOL	mIndexLocked;			// if TRUE, index buffer is being or has been written to in client memory
-	BOOL	mFinal;			// if TRUE, buffer can not be mapped again
-	BOOL	mEmpty;			// if TRUE, client buffer is empty (or NULL). Old values have been discarded.	
-	mutable BOOL	mMappable;     // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
+
+	U32		mMappedDataUsingVBOs : 1;
+	U32		mMappedIndexDataUsingVBOs : 1;
+	U32		mVertexLocked : 1;			// if TRUE, vertex buffer is being or has been written to in client memory
+	U32		mIndexLocked : 1;			// if TRUE, index buffer is being or has been written to in client memory
+	U32		mFinal : 1;			// if TRUE, buffer can not be mapped again
+	U32		mEmpty : 1;			// if TRUE, client buffer is empty (or NULL). Old values have been discarded.	
+	
+	mutable bool	mMappable;     // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
 	S32		mOffsets[TYPE_MAX];
 
 	std::vector<MappedRegion> mMappedVertexRegions;
@@ -296,6 +308,7 @@ class LLVertexBuffer : public LLRefCount
 	void placeFence() const;
 	void waitFence() const;
 
+	static S32 determineUsage(S32 usage);
 
 private:
 	static LLPrivateMemoryPool* sPrivatePoolp ;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index 40b0cf47ac5..eada38eaaa0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -55,6 +55,12 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+        float a = max(dot(n,l),0.0);
+        return a;
+}
+
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 8c96d553424..5c36118a50a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -64,6 +64,12 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+        float a = max(dot(n,l),0.0);
+        return a;
+}
+
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index c0edddc40a5..d6149fcc32a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -59,6 +59,12 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+        float a = max(dot(n,l),0.0);
+        return a;
+}
+
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
index 83815b17860..9629cfe824e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
@@ -61,6 +61,12 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+        float a = max(dot(n,l),0.0);
+        return a;
+}
+
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 //get light vector
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
index 1660f9687eb..1586aab0f25 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -63,6 +63,12 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+        float a = max(dot(n,l),0.0);
+        return a;
+}
+
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
index 84c27edb268..44aaa98b977 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -60,6 +60,12 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+        float a = max(dot(n,l),0.0);
+        return a;
+}
+
 float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 5de363e03cc..6db21386887 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -730,7 +730,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 
 	vector< pair<string, S32> > shaders;
 	shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );
 	shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );
 	shaders.push_back( make_pair( "lighting/lightFuncV.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
 	shaders.push_back( make_pair( "lighting/sumLightsV.glsl",				sum_lights_class ) );
@@ -1102,19 +1102,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
+		gDeferredSkinnedAlphaProgram.mFeatures.atmosphericHelpers = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
-		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
-		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false;
 		gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		
 		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
+		
+		// Hack to include uniforms for lighting without linking in lighting file
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
 	}
 
 	if (success)
@@ -1231,11 +1237,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredAlphaProgram.mName = "Deferred Alpha Shader";
-		gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
+		gDeferredAlphaProgram.mFeatures.atmosphericHelpers = true;
+		gDeferredAlphaProgram.mFeatures.calculatesLighting = false;
 		gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
-		gDeferredAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAlphaProgram.mFeatures.hasLighting = false;
 		gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
@@ -1251,7 +1258,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+
 		success = gDeferredAlphaProgram.createShader(NULL, NULL);
+
+		// Hack
+		gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
+		gDeferredAlphaProgram.mFeatures.hasLighting = true;
 	}
 
 	if (success)
@@ -1394,19 +1406,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader";
+		gDeferredAvatarAlphaProgram.mFeatures.atmosphericHelpers = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true;
-		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true;
+		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false;
 		gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
-		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false;
 		gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+
 		success = gDeferredAvatarAlphaProgram.createShader(NULL, &mAvatarUniforms);
+
+		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true;
+		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
 	}
 
 	if (success)
-- 
GitLab