diff options
| author | Graham Madarasz (Graham) <graham@lindenlab.com> | 2013-03-04 08:57:58 -0800 | 
|---|---|---|
| committer | Graham Madarasz (Graham) <graham@lindenlab.com> | 2013-03-04 08:57:58 -0800 | 
| commit | 4e81a84abd2c928dbdc6c4e2a3a348494d205edf (patch) | |
| tree | 7066e1bbe40d44db58660ea65ef126d32b513c62 /indra | |
| parent | 3849ee79c3810226d1129bcbeb6bd69144aba243 (diff) | |
| parent | da2caa46406d07b4b093bc17966ee23d87819f7c (diff) | |
Performance improvements. Faster threadsaferefcount, faster instancetracker, use hashtable and pre-hashed strings for GLSL uniform lookup, and use dup_handles curl interface to avoid re-initing ares resolvers expensively.
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llmath/llvolume.cpp | 99 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 3 | ||||
| -rw-r--r-- | indra/llrender/llgl.cpp | 37 | ||||
| -rw-r--r-- | indra/llrender/llglheaders.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 40 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 47 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 3 | ||||
| -rwxr-xr-x | indra/newview/llagent.cpp | 33 | ||||
| -rw-r--r-- | indra/newview/llagent.h | 2 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 2 | ||||
| -rwxr-xr-x | indra/newview/llface.cpp | 37 | ||||
| -rwxr-xr-x | indra/newview/llmeshrepository.cpp | 5 | ||||
| -rwxr-xr-x | indra/newview/llvoavatar.cpp | 258 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.h | 3 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 35 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 47 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 41 | 
17 files changed, 445 insertions, 249 deletions
| diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 02c8d2b86f..c476f8593b 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5187,7 +5187,8 @@ LLVolumeFace::LLVolumeFace() :  	mTexCoords(NULL),  	mIndices(NULL),  	mWeights(NULL), -	mOctree(NULL) +	mOctree(NULL), +	mOptimized(FALSE)  {  	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);  	mExtents[0].splat(-0.5f); @@ -5294,6 +5295,8 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);  	} +	mOptimized = src.mOptimized; +  	//delete   	return *this;  } @@ -5517,14 +5520,14 @@ class LLVCacheVertexData  public:  	S32 mIdx;  	S32 mCacheTag; -	F32 mScore; +	F64 mScore;  	U32 mActiveTriangles;  	std::vector<LLVCacheTriangleData*> mTriangles;  	LLVCacheVertexData()  	{  		mCacheTag = -1; -		mScore = 0.f; +		mScore = 0.0;  		mActiveTriangles = 0;  		mIdx = -1;  	} @@ -5534,13 +5537,13 @@ class LLVCacheTriangleData  {  public:  	bool mActive; -	F32 mScore; +	F64 mScore;  	LLVCacheVertexData* mVertex[3];  	LLVCacheTriangleData()  	{  		mActive = true; -		mScore = 0.f; +		mScore = 0.0;  		mVertex[0] = mVertex[1] = mVertex[2] = NULL;  	} @@ -5551,7 +5554,7 @@ public:  		{  			if (mVertex[i])  			{ -				llassert_always(mVertex[i]->mActiveTriangles > 0); +				llassert(mVertex[i]->mActiveTriangles > 0);  				mVertex[i]->mActiveTriangles--;  			}  		} @@ -5563,44 +5566,44 @@ public:  	}  }; -const F32 FindVertexScore_CacheDecayPower = 1.5f; -const F32 FindVertexScore_LastTriScore = 0.75f; -const F32 FindVertexScore_ValenceBoostScale = 2.0f; -const F32 FindVertexScore_ValenceBoostPower = 0.5f; +const F64 FindVertexScore_CacheDecayPower = 1.5; +const F64 FindVertexScore_LastTriScore = 0.75; +const F64 FindVertexScore_ValenceBoostScale = 2.0; +const F64 FindVertexScore_ValenceBoostPower = 0.5;  const U32 MaxSizeVertexCache = 32; +const F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3); -F32 find_vertex_score(LLVCacheVertexData& data) +F64 find_vertex_score(LLVCacheVertexData& data)  { -	if (data.mActiveTriangles == 0) -	{ //no triangle references this vertex -		return -1.f; -	} +	F64 score = -1.0; -	F32 score = 0.f; - -	S32 cache_idx = data.mCacheTag; +	if (data.mActiveTriangles >= 0) +	{  +		score = 0.0; +		 +		S32 cache_idx = data.mCacheTag; -	if (cache_idx < 0) -	{ -		//not in cache -	} -	else -	{ -		if (cache_idx < 3) -		{ //vertex was in the last triangle -			score = FindVertexScore_LastTriScore; +		if (cache_idx < 0) +		{ +			//not in cache  		}  		else -		{ //more points for being higher in the cache -			F32 scaler = 1.f/(MaxSizeVertexCache-3); -			score = 1.f-((cache_idx-3)*scaler); -			score = powf(score, FindVertexScore_CacheDecayPower); +		{ +			if (cache_idx < 3) +			{ //vertex was in the last triangle +				score = FindVertexScore_LastTriScore; +			} +			else +			{ //more points for being higher in the cache +				score = 1.0-((cache_idx-3)*FindVertexScore_Scaler); +				score = pow(score, FindVertexScore_CacheDecayPower); +			}  		} -	} -	//bonus points for having low valence -	F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); -	score += FindVertexScore_ValenceBoostScale * valence_boost; +		//bonus points for having low valence +		F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); +		score += FindVertexScore_ValenceBoostScale * valence_boost; +	}  	return score;  } @@ -5720,7 +5723,7 @@ public:  			if (mCache[i])  			{  				mCache[i]->mScore = find_vertex_score(*(mCache[i])); -				llassert_always(mCache[i]->mCacheTag == i); +				llassert(mCache[i]->mCacheTag == i);  			}  		} @@ -5728,11 +5731,14 @@ public:  		//update triangle scores  		for (U32 i = 0; i < MaxSizeVertexCache+3; ++i)  		{ -			if (mCache[i]) +			LLVCacheVertexData* data = mCache[i]; +			if (data)  			{ -				for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j) +				U32 count = data->mTriangles.size(); + +				for (U32 j = 0; j < count; ++j)  				{ -					LLVCacheTriangleData* tri = mCache[i]->mTriangles[j]; +					LLVCacheTriangleData* tri = data->mTriangles[j];  					if (tri->mActive)  					{  						tri->mScore = tri->mVertex[0]->mScore; @@ -5753,7 +5759,7 @@ public:  		{  			if (mCache[i])  			{ -				llassert_always(mCache[i]->mCacheTag == -1); +				llassert(mCache[i]->mCacheTag == -1);  				mCache[i] = NULL;  			}  		} @@ -5765,6 +5771,9 @@ void LLVolumeFace::cacheOptimize()  { //optimize for vertex cache according to Forsyth method:     // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html +	llassert(!mOptimized); +	mOptimized = TRUE; +  	LLVCacheLRU cache;  	if (mNumVertices < 3) @@ -5810,12 +5819,14 @@ void LLVolumeFace::cacheOptimize()  	for (U32 i = 0; i < mNumVertices; i++)  	{ //initialize score values (no cache -- might try a fifo cache here) -		vertex_data[i].mScore = find_vertex_score(vertex_data[i]); -		vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size(); +		LLVCacheVertexData& data = vertex_data[i]; + +		data.mScore = find_vertex_score(data); +		data.mActiveTriangles = data.mTriangles.size(); -		for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j) +		for (U32 j = 0; j < data.mActiveTriangles; ++j)  		{ -			vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore; +			data.mTriangles[j]->mScore += data.mScore;  		}  	} diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c845556557..99158c1c44 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -933,6 +933,9 @@ public:  	LLOctreeNode<LLVolumeTriangle>* mOctree; +	//whether or not face has been cache optimized +	BOOL mOptimized; +  private:  	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);  	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 9d06dd6904..89f1f36297 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -59,6 +59,7 @@ BOOL gDebugGL = FALSE;  BOOL gClothRipple = FALSE;  BOOL gHeadlessClient = FALSE;  BOOL gGLActive = FALSE; +BOOL gGLDebugLoggingEnabled = TRUE;  static const std::string HEADLESS_VENDOR_STRING("Linden Lab");  static const std::string HEADLESS_RENDERER_STRING("Headless"); @@ -72,6 +73,7 @@ std::ofstream gFailLog;  #define APIENTRY  #endif +  void APIENTRY gl_debug_callback(GLenum source,                                  GLenum type,                                  GLuint id, @@ -80,22 +82,25 @@ void APIENTRY gl_debug_callback(GLenum source,                                  const GLchar* message,                                  GLvoid* userParam)  { -	if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) -	{ -		llwarns << "----- GL ERROR --------" << llendl; -	} -	else +	if (gGLDebugLoggingEnabled)  	{ -		llwarns << "----- GL WARNING -------" << llendl; -	} -	llwarns << "Type: " << std::hex << type << llendl; -	llwarns << "ID: " << std::hex << id << llendl; -	llwarns << "Severity: " << std::hex << severity << llendl; -	llwarns << "Message: " << message << llendl; -	llwarns << "-----------------------" << llendl; -	if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) -	{ -		llerrs << "Halting on GL Error" << llendl; +		if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) +		{ +			llwarns << "----- GL ERROR --------" << llendl; +		} +		else +		{ +			llwarns << "----- GL WARNING -------" << llendl; +		} +		llwarns << "Type: " << std::hex << type << llendl; +		llwarns << "ID: " << std::hex << id << llendl; +		llwarns << "Severity: " << std::hex << severity << llendl; +		llwarns << "Message: " << message << llendl; +		llwarns << "-----------------------" << llendl; +		if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) +		{ +			llerrs << "Halting on GL Error" << llendl; +		}  	}  }  #endif @@ -253,6 +258,7 @@ PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;  PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;  PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;  PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL; +PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;  //GL_ARB_debug_output  PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL; @@ -1224,6 +1230,7 @@ void LLGLManager::initExtensions()  		glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");  		glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");  		glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); +		glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");  	}  	if (mHasDebugOutput)  	{ diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 509de51f4d..a92ed428da 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -533,6 +533,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;  extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;  extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;  extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; +extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;  #elif LL_WINDOWS @@ -771,6 +772,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;  extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;  extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;  extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; +extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;  //GL_ARB_debug_output  extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index a12e9caf4c..5801946a74 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -225,26 +225,15 @@ void LLTexUnit::disable(void)  bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  {  	stop_glerror(); -	if (mIndex < 0) return false; - +	if (mIndex >= 0) +	{  	gGL.flush();  	LLImageGL* gl_tex = NULL ; -	if (texture == NULL || !(gl_tex = texture->getGLTexture())) +		if (texture != NULL && (gl_tex = texture->getGLTexture()))  	{ -		llwarns << "NULL LLTexUnit::bind texture" << llendl; -		return false; -	} - -	if (!gl_tex->getTexName()) //if texture does not exist +			if (gl_tex->getTexName()) //if texture exists  	{ -		//if deleted, will re-generate it immediately -		texture->forceImmediateUpdate() ; - -		gl_tex->forceUpdateBindStats() ; -		return texture->bindDefaultImage(mIndex); -	} -  	//in audit, replace the selected texture by the default one.  	if ((mCurrTexture != gl_tex->getTexName()) || forceBind)  	{ @@ -265,6 +254,27 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  			setTextureFilteringOption(gl_tex->mFilterOption);  		}  	} +			} +			else +			{ +				//if deleted, will re-generate it immediately +				texture->forceImmediateUpdate() ; + +				gl_tex->forceUpdateBindStats() ; +				return texture->bindDefaultImage(mIndex); +			} +		} +		else +		{ +			llwarns << "NULL LLTexUnit::bind texture" << llendl; +			return false; +		} +	} +	else +	{ // mIndex < 0 +		return false; +	} +  	return true;  } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index dfbd8cd4ee..f152911b24 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -85,6 +85,7 @@ const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);  //static  LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);  LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB); +LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_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); @@ -199,7 +200,10 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)  		if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)  		{  			glBufferDataARB(mType, size, 0, mUsage); -			ret = (U8*) ll_aligned_malloc_16(size); +			if (mUsage != GL_DYNAMIC_COPY_ARB) +			{ //data will be provided by application +				ret = (U8*) ll_aligned_malloc_16(size); +			}  		}  		else  		{ //always use a true hint of static draw when allocating non-client-backed buffers @@ -393,6 +397,7 @@ void LLVertexBuffer::seedPools()  {  	sStreamVBOPool.seedPool();  	sDynamicVBOPool.seedPool(); +	sDynamicCopyVBOPool.seedPool();  	sStreamIBOPool.seedPool();  	sDynamicIBOPool.seedPool();  } @@ -875,6 +880,7 @@ void LLVertexBuffer::cleanupClass()  	sDynamicIBOPool.cleanup();  	sStreamVBOPool.cleanup();  	sDynamicVBOPool.cleanup(); +	sDynamicCopyVBOPool.cleanup();  	if(sPrivatePoolp)  	{ @@ -911,13 +917,16 @@ S32 LLVertexBuffer::determineUsage(S32 usage)  	if (ret_usage && ret_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 -			ret_usage = GL_STREAM_DRAW_ARB; -		} -		else +		if (ret_usage != GL_DYNAMIC_COPY_ARB)  		{ -			ret_usage = GL_DYNAMIC_DRAW_ARB; +			if (sDisableVBOMapping) +			{ //always use stream draw if VBO mapping is disabled +				ret_usage = GL_STREAM_DRAW_ARB; +			} +			else +			{ +				ret_usage = GL_DYNAMIC_DRAW_ARB; +			}  		}  	} @@ -1067,10 +1076,15 @@ void LLVertexBuffer::genBuffer(U32 size)  	{  		mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);  	} -	else +	else if (mUsage == GL_DYNAMIC_DRAW_ARB)  	{  		mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);  	} +	else +	{ +		mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize); +	} +  	sGLCount++;  } @@ -1820,6 +1834,8 @@ void LLVertexBuffer::unmapBuffer()  	if (mMappedData && mVertexLocked)  	{ +		llassert(mUsage != GL_DYNAMIC_COPY_ARB); +		  		LLFastTimer t(FTM_VBO_UNMAP);  		bindGLBuffer(true);  		updated_all = mIndexLocked; //both vertex and index buffers done updating @@ -2094,22 +2110,15 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)  	if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))  	{ -		LLFastTimer t(FTM_BIND_GL_BUFFER); -		/*if (sMapped) -		{ -			llerrs << "VBO bound while another VBO mapped!" << llendl; -		}*/ +		//LLFastTimer t(FTM_BIND_GL_BUFFER); <-- this timer is showing up as a hotspot (irony) +		  		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);  		sGLRenderBuffer = mGLBuffer;  		sBindCount++;  		sVBOActive = true; -		if (mGLArray) -		{ -			llassert(sGLRenderArray == mGLArray); -			//mCachedRenderBuffer = mGLBuffer; -		} - +		llassert(!mGLArray || sGLRenderArray == mGLArray); +		  		ret = true;  	} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 11fa4ab6a0..a3400ae80c 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -125,9 +125,10 @@ public:  	static LLVBOPool sStreamVBOPool;  	static LLVBOPool sDynamicVBOPool; +	static LLVBOPool sDynamicCopyVBOPool;  	static LLVBOPool sStreamIBOPool;  	static LLVBOPool sDynamicIBOPool; - +	  	static std::list<U32> sAvailableVAOName;  	static U32 sCurVAOName; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index b6fd7bc9c2..f0eee24fef 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3062,6 +3062,30 @@ void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request)  	sendReliableMessage();  } +// Send a message to the region to stop the NULL animation state +// This will reset animation state overrides for the agent. +void LLAgent::sendAnimationStateReset() +{ +	if (gAgentID.isNull() || !mRegionp) +	{ +		return; +	} + +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_AgentAnimation); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, getID()); +	msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + +	msg->nextBlockFast(_PREHASH_AnimationList); +	msg->addUUIDFast(_PREHASH_AnimID, LLUUID::null ); +	msg->addBOOLFast(_PREHASH_StartAnim, FALSE); + +	msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); +	msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); +	sendReliableMessage(); +} +  void LLAgent::sendWalkRun(bool running)  {  	LLMessageSystem* msgsys = gMessageSystem; @@ -4140,6 +4164,8 @@ void LLAgent::stopCurrentAnimations()  	// avatar, propagating this change back to the server.  	if (isAgentAvatarValid())  	{ +		LLDynamicArray<LLUUID> anim_ids; +  		for ( LLVOAvatar::AnimIterator anim_it =  			      gAgentAvatarp->mPlayingAnimations.begin();  		      anim_it != gAgentAvatarp->mPlayingAnimations.end(); @@ -4157,10 +4183,15 @@ void LLAgent::stopCurrentAnimations()  				// stop this animation locally  				gAgentAvatarp->stopMotion(anim_it->first, TRUE);  				// ...and tell the server to tell everyone. -				sendAnimationRequest(anim_it->first, ANIM_REQUEST_STOP); +				anim_ids.push_back(anim_it->first);  			}  		} +		sendAnimationRequests(anim_ids, ANIM_REQUEST_STOP); + +		// Tell the region to clear any animation state overrides. +		sendAnimationStateReset(); +  		// re-assert at least the default standing animation, because  		// viewers get confused by avs with no associated anims.  		sendAnimationRequest(ANIM_AGENT_STAND, diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 99904e118c..bec9352f5f 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -431,6 +431,8 @@ public:  	void			onAnimStop(const LLUUID& id);  	void			sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request);  	void			sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); +	void			sendAnimationStateReset(); +  	void			endAnimationUpdateUI();  	void			unpauseAnimation() { mPauseRequest = NULL; }  	BOOL			getCustomAnim() const { return mCustomAnim; } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 4137084ebe..7e95046479 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -461,6 +461,8 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&  				}  			}  		} +        // Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0 +        // MAINT-755  		cube_map->disable();  		cube_map->restoreMatrix();  	} diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 3c7a49d5ce..43d21137b5 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -51,7 +51,9 @@  #include "llviewerregion.h"  #include "llviewerwindow.h"  #include "llviewershadermgr.h" +#include "llvoavatar.h" +extern BOOL gGLDebugLoggingEnabled;  #define LL_MAX_INDICES_COUNT 1000000 @@ -328,6 +330,12 @@ void LLFace::dirtyTexture()  		if (vobj)  		{  			vobj->mLODChanged = TRUE; + +			LLVOAvatar* avatar = vobj->getAvatar(); +			if (avatar) +			{ //avatar render cost may have changed +				avatar->updateVisualComplexity(); +			}  		}  		gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);  	}		 @@ -1162,6 +1170,15 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal"); + +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK("Face Feedback"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_POSITION("Feedback Position"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_NORMAL("Feedback  Normal"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_TEXTURE("Feedback  Texture"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_COLOR("Feedback  Color"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_EMISSIVE("Feedback  Emissive"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_BINORMAL("Feedback Binormal"); +  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail");  static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos"); @@ -1385,12 +1402,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  #ifdef GL_TRANSFORM_FEEDBACK_BUFFER  	if (use_transform_feedback && +		mVertexBuffer->getUsage() == GL_DYNAMIC_COPY_ARB &&  		gTransformPositionProgram.mProgramObject && //transform shaders are loaded  		mVertexBuffer->useVBOs() && //target buffer is in VRAM  		!rebuild_weights && //TODO: add support for weights  		!volume.isUnique()) //source volume is NOT flexi  	{ //use transform feedback to pack vertex buffer - +		//gGLDebugLoggingEnabled = TRUE; +		LLFastTimer t(FTM_FACE_GEOM_FEEDBACK);  		LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get();  		if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) @@ -1407,7 +1426,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_pos)  		{ -			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_POSITION);  			gTransformPositionProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); @@ -1420,7 +1439,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			vp[1] = 0;  			vp[2] = 0;  			vp[3] = 0; -						 +			  			gTransformPositionProgram.uniform1i(sTextureIndexIn, val);  			glBeginTransformFeedback(GL_POINTS);  			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); @@ -1432,7 +1451,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_color)  		{ -			LLFastTimer t(FTM_FACE_GEOM_COLOR); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_COLOR);  			gTransformColorProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); @@ -1448,7 +1467,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_emissive)  		{ -			LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_EMISSIVE);  			gTransformColorProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); @@ -1469,7 +1488,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_normal)  		{ -			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_NORMAL);  			gTransformNormalProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); @@ -1482,7 +1501,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_binormal)  		{ -			LLFastTimer t(FTM_FACE_GEOM_BINORMAL); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_BINORMAL);  			gTransformBinormalProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount); @@ -1495,7 +1514,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_tcoord)  		{ -			LLFastTimer t(FTM_FACE_GEOM_TEXTURE); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_TEXTURE);  			gTransformTexCoordProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); @@ -1518,13 +1537,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		}  		glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); -  		gGL.popMatrix();  		if (cur_shader)  		{  			cur_shader->bind();  		} +		//gGLDebugLoggingEnabled = FALSE;  	}  	else  #endif diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1223615079..ae48898e82 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -588,7 +588,7 @@ void LLMeshRepoThread::run()  					if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit  					{  						mMutex->lock(); -						mLODReqQ.push(req) ;  +						mLODReqQ.push(req);   						mMutex->unlock();  					}  				} @@ -1200,8 +1200,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat  			LLMutexLock lock(mHeaderMutex);  			mMeshHeaderSize[mesh_id] = header_size;  			mMeshHeader[mesh_id] = header; -			} - +		}  		LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time. diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 62e93b7a53..4efd59685e 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -688,6 +688,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mFullyLoaded(FALSE),  	mPreviousFullyLoaded(FALSE),  	mFullyLoadedInitialized(FALSE), +	mVisualComplexity(0), +	mVisualComplexityStale(TRUE),  	mSupportsAlphaLayers(FALSE),  	mLoadedCallbacksPaused(FALSE),  	mHasPelvisOffset( FALSE ), @@ -3434,12 +3436,23 @@ void LLVOAvatar::slamPosition()  bool LLVOAvatar::isVisuallyMuted() const  { -	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); -	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); +	bool ret = false; + +	if (!isSelf()) +	{ +		static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); +		static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); +		static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); -	return LLMuteList::getInstance()->isMuted(getID()) || +		U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5)); + +		ret = LLMuteList::getInstance()->isMuted(getID()) ||  			(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || -			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || +			(mVisualComplexity > max_cost && max_render_cost > 0); +	} + +	return ret;  }  //------------------------------------------------------------------------ @@ -4139,46 +4152,6 @@ bool LLVOAvatar::shouldAlphaMask()  } -U32 LLVOAvatar::renderSkinnedAttachments() -{ -	/*U32 num_indices = 0; -	 -	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX |  -							LLVertexBuffer::MAP_NORMAL |  -							LLVertexBuffer::MAP_TEXCOORD0 | -							LLVertexBuffer::MAP_COLOR | -							LLVertexBuffer::MAP_WEIGHT4; - -	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  -		 iter != mAttachmentPoints.end(); -		 ++iter) -	{ -		LLViewerJointAttachment* attachment = iter->second; -		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -			 attachment_iter != attachment->mAttachedObjects.end(); -			 ++attachment_iter) -		{ -			const LLViewerObject* attached_object = (*attachment_iter); -			if (attached_object && !attached_object->isHUDAttachment()) -			{ -				const LLDrawable* drawable = attached_object->mDrawable; -				if (drawable) -				{ -					for (S32 i = 0; i < drawable->getNumFaces(); ++i) -					{ -						LLFace* face = drawable->getFace(i); -						if (face->isState(LLFace::RIGGED)) -						{ -							 -				} -			} -		} -	} - -	return num_indices;*/ -	return 0; -} -  //-----------------------------------------------------------------------------  // renderSkinned()  //----------------------------------------------------------------------------- @@ -4336,21 +4309,23 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  		BOOL first_pass = TRUE;  		if (!LLDrawPoolAvatar::sSkipOpaque)  		{ +			bool muted = isVisuallyMuted(); +  			if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)  			{ -				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) +				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || muted)  				{  					num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);  					first_pass = FALSE;  				}  			} -			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) +			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || muted)  			{  				num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);  				first_pass = FALSE;  			} -			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) +			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || muted)  			{  				num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);  				first_pass = FALSE; @@ -6090,6 +6065,8 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o  		return 0;  	} +	mVisualComplexityStale = TRUE; +  	if (viewer_object->isSelected())  	{  		LLSelectMgr::getInstance()->updateSelectionCenter(); @@ -6244,6 +6221,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)  		if (attachment->isObjectAttached(viewer_object))  		{ +			mVisualComplexityStale = TRUE;  			cleanupAttachedMesh( viewer_object );  			attachment->removeObject(viewer_object);  			lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl; @@ -8456,7 +8434,7 @@ void LLVOAvatar::updateImpostors()  BOOL LLVOAvatar::isImpostor() const  { -	return (isVisuallyMuted() || (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE; +	return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;  } @@ -8501,6 +8479,8 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d  void LLVOAvatar::idleUpdateRenderCost()  { +	static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); +  	static const U32 ARC_BODY_PART_COST = 200;  	static const U32 ARC_LIMIT = 20000; @@ -8511,123 +8491,147 @@ void LLVOAvatar::idleUpdateRenderCost()  		setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));  	} -	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) +	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME) && max_render_cost == 0)  	{  		return;  	} -	U32 cost = 0; -	LLVOVolume::texture_cost_t textures; - -	for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) +	if (mVisualComplexityStale)  	{ -		const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); -		ETextureIndex tex_index = baked_dict->mTextureIndex; -		if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) +		mVisualComplexityStale = FALSE; +		U32 cost = 0; +		LLVOVolume::texture_cost_t textures; + +		for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)  		{ -			if (isTextureVisible(tex_index)) +			const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); +			ETextureIndex tex_index = baked_dict->mTextureIndex; +			if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))  			{ -				cost +=ARC_BODY_PART_COST; +				if (isTextureVisible(tex_index)) +				{ +					cost +=ARC_BODY_PART_COST; +				}  			}  		} -	} -	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  -		 iter != mAttachmentPoints.end(); -		 ++iter) -	{ -		LLViewerJointAttachment* attachment = iter->second; -		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -			 attachment_iter != attachment->mAttachedObjects.end(); -			 ++attachment_iter) +		for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  +			 iter != mAttachmentPoints.end(); +			 ++iter)  		{ -			const LLViewerObject* attached_object = (*attachment_iter); -			if (attached_object && !attached_object->isHUDAttachment()) +			LLViewerJointAttachment* attachment = iter->second; +			for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); +				 attachment_iter != attachment->mAttachedObjects.end(); +				 ++attachment_iter)  			{ -				textures.clear(); -				const LLDrawable* drawable = attached_object->mDrawable; -				if (drawable) +				const LLViewerObject* attached_object = (*attachment_iter); +				if (attached_object && !attached_object->isHUDAttachment())  				{ -					const LLVOVolume* volume = drawable->getVOVolume(); -					if (volume) +					textures.clear(); +					const LLDrawable* drawable = attached_object->mDrawable; +					if (drawable)  					{ -						cost += volume->getRenderCost(textures); - -						const_child_list_t children = volume->getChildren(); -						for (const_child_list_t::const_iterator child_iter = children.begin(); -							  child_iter != children.end(); -							  ++child_iter) +						const LLVOVolume* volume = drawable->getVOVolume(); +						if (volume)  						{ -							LLViewerObject* child_obj = *child_iter; -							LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj ); -							if (child) +							cost += volume->getRenderCost(textures); + +							const_child_list_t children = volume->getChildren(); +							for (const_child_list_t::const_iterator child_iter = children.begin(); +								  child_iter != children.end(); +								  ++child_iter)  							{ -								cost += child->getRenderCost(textures); +								LLViewerObject* child_obj = *child_iter; +								LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj ); +								if (child) +								{ +									cost += child->getRenderCost(textures); +								}  							} -						} -						for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) -						{ -							// add the cost of each individual texture in the linkset -							cost += iter->second; +							for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) +							{ +								// add the cost of each individual texture in the linkset +								cost += iter->second; +							}  						}  					}  				}  			} -		} -	} +		} -	// Diagnostic output to identify all avatar-related textures. -	// Does not affect rendering cost calculation. -	// Could be wrapped in a debug option if output becomes problematic. -	if (isSelf()) -	{ -		// print any attachment textures we didn't already know about. -		for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it) +		// Diagnostic output to identify all avatar-related textures. +		// Does not affect rendering cost calculation. +		// Could be wrapped in a debug option if output becomes problematic. +		if (isSelf())  		{ -			LLUUID image_id = it->first; -			if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) -				continue; -			if (all_textures.find(image_id) == all_textures.end()) +			// print any attachment textures we didn't already know about. +			for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it) +			{ +				LLUUID image_id = it->first; +				if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) +					continue; +				if (all_textures.find(image_id) == all_textures.end()) +				{ +					// attachment texture not previously seen. +					llinfos << "attachment_texture: " << image_id.asString() << llendl; +					all_textures.insert(image_id); +				} +			} + +			// print any avatar textures we didn't already know about +			for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); +				 iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); +				 ++iter)  			{ -				// attachment texture not previously seen. -				llinfos << "attachment_texture: " << image_id.asString() << llendl; -				all_textures.insert(image_id); +				const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; +				// TODO: MULTI-WEARABLE: handle multiple textures for self +				const LLViewerTexture* te_image = getImage(iter->first,0); +				if (!te_image) +					continue; +				LLUUID image_id = te_image->getID(); +				if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) +					continue; +				if (all_textures.find(image_id) == all_textures.end()) +				{ +					llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl; +					all_textures.insert(image_id); +				}  			}  		} -		// print any avatar textures we didn't already know about -		for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); -			 iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); -			 ++iter) -		{ -			const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second; -			// TODO: MULTI-WEARABLE: handle multiple textures for self -			const LLViewerTexture* te_image = getImage(iter->first,0); -			if (!te_image) -				continue; -			LLUUID image_id = te_image->getID(); -			if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) -				continue; -			if (all_textures.find(image_id) == all_textures.end()) +		if (isSelf() && max_render_cost > 0 && mVisualComplexity != cost) +		{ //pop up notification that you have exceeded a render cost limit +			if (cost > max_render_cost+max_render_cost/2) +			{ +				LLNotificationsUtil::add("ExceededHighDetailRenderCost"); +			} +			else if (cost > max_render_cost)  			{ -				llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl; -				all_textures.insert(image_id); +				LLNotificationsUtil::add("ExceededMidDetailRenderCost"); +			} +			else if (cost > max_render_cost/2) +			{ +				LLNotificationsUtil::add("ExceededLowDetailRenderCost");  			}  		} + +		mVisualComplexity = cost;  	} -	std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); -	setDebugText(llformat("%s %d", viz_string.c_str(), cost)); -	mVisualComplexity = cost; -	F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); -	F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); -	mText->setColor(LLColor4(red,green,0,1)); +	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) +	{ +		std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); +		setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity)); +		F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); +		F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f); +		mText->setColor(LLColor4(red,green,0,1)); +	}  }  // static diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 1adb680962..e6569c557c 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -252,6 +252,7 @@ public:  	static void		invalidateNameTags();  	void			addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);  	void 			idleUpdateRenderCost(); +	void			updateVisualComplexity() { mVisualComplexityStale = TRUE; }  	void 			idleUpdateBelowWater();  	//-------------------------------------------------------------------- @@ -314,6 +315,7 @@ private:  	BOOL			mFullyLoadedInitialized;  	S32				mFullyLoadedFrameCounter;  	S32				mVisualComplexity; +	BOOL			mVisualComplexityStale;  	LLFrameTimer	mFullyLoadedTimer;  	LLFrameTimer	mRuthTimer; @@ -437,7 +439,6 @@ public:  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass);  	F32			getLastSkinTime() { return mLastSkinTime; } -	U32			renderSkinnedAttachments();  	U32 		renderTransparent(BOOL first_pass);  	void 		renderCollisionVolumes();  	static void	deleteCachedImages(bool clearAll=true); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c0f80cf855..6a18534484 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -99,6 +99,8 @@ static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");  static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");  static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures"); +extern BOOL gGLDebugLoggingEnabled; +  // Implementation class of LLMediaDataClientObject.  See llmediadataclient.h  class LLMediaDataClientObjectImpl : public LLMediaDataClientObject  { @@ -1067,7 +1069,9 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  					break;  				}  				volume->genBinormals(i); +				//gGLDebugLoggingEnabled = TRUE;  				LLFace::cacheFaceInVRAM(face); +				//gGLDebugLoggingEnabled = FALSE;  			}  		} @@ -1116,6 +1120,12 @@ void LLVOVolume::notifyMeshLoaded()  {   	mSculptChanged = TRUE;  	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + +	LLVOAvatar* avatar = getAvatar(); +	if (avatar) +	{ +		avatar->updateVisualComplexity(); +	}  }  // sculpt replaces generate() for sculpted surfaces @@ -4830,6 +4840,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  	U32 buffer_usage = group->mBufferUsage; +	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +	if (use_transform_feedback && +		gTransformPositionProgram.mProgramObject && //transform shaders are loaded +		buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM +		!(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights +	{ +		buffer_usage = GL_DYNAMIC_COPY_ARB; +	} +  #if LL_DARWIN  	// HACK from Leslie:  	// Disable VBO usage for alpha on Mac OS X because it kills the framerate @@ -4889,6 +4909,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  	//NEVER use more than 16 texture index channels (workaround for prevalent driver bug)  	texture_index_channels = llmin(texture_index_channels, 16); +	bool flexi = false; +  	while (face_iter != faces.end())  	{  		//pull off next face @@ -4915,6 +4937,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		U32 index_count = facep->getIndicesCount();  		U32 geom_count = facep->getGeomCount(); +		flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); +  		//sum up vertices needed for this render batch  		std::vector<LLFace*>::iterator i = face_iter;  		++i; @@ -4983,6 +5007,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  						}  						++i; + +						flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); +  						index_count += facep->getIndicesCount();  						geom_count += facep->getGeomCount(); @@ -5012,10 +5039,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  					++i;  					index_count += facep->getIndicesCount();  					geom_count += facep->getGeomCount(); + +					flexi = flexi || facep->getViewerObject()->getVolume()->isUnique();  				}  			}  		} + +		if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) +		{ +			buffer_usage = GL_STREAM_DRAW_ARB; +		} +  		//create vertex buffer  		LLVertexBuffer* buffer = NULL; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 92c5ac8583..690bf64798 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -253,15 +253,15 @@ LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");  static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");  static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort"); -static LLStaticHashedString sTint("tint");
 -static LLStaticHashedString sAmbiance("ambiance");
 -static LLStaticHashedString sAlphaScale("alpha_scale");
 -static LLStaticHashedString sNormMat("norm_mat");
 -static LLStaticHashedString sOffset("offset");
 -static LLStaticHashedString sScreenRes("screenRes");
 -static LLStaticHashedString sDelta("delta");
 -static LLStaticHashedString sDistFactor("dist_factor");
 -static LLStaticHashedString sKern("kern");
 +static LLStaticHashedString sTint("tint"); +static LLStaticHashedString sAmbiance("ambiance"); +static LLStaticHashedString sAlphaScale("alpha_scale"); +static LLStaticHashedString sNormMat("norm_mat"); +static LLStaticHashedString sOffset("offset"); +static LLStaticHashedString sScreenRes("screenRes"); +static LLStaticHashedString sDelta("delta"); +static LLStaticHashedString sDistFactor("dist_factor"); +static LLStaticHashedString sKern("kern");  static LLStaticHashedString sKernScale("kern_scale");  //---------------------------------------- @@ -10258,6 +10258,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		avatar->mImpostor.bindTarget();  	} +	F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + +	if (muted) +	{ //disable alpha masking for muted avatars (get whole skin silhouette) +		LLDrawPoolAvatar::sMinimumAlpha = 0.f; +	} +  	if (LLPipeline::sRenderDeferred)  	{  		avatar->mImpostor.clear(); @@ -10272,6 +10279,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		renderGeom(camera);  	} +	LLDrawPoolAvatar::sMinimumAlpha = old_alpha; +		  	{ //create alpha mask based on depth buffer (grey out if muted)  		LLFastTimer t(FTM_IMPOSTOR_BACKGROUND);  		if (LLPipeline::sRenderDeferred) @@ -10285,6 +10294,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		if (muted)  		{  			gGL.setColorMask(true, true); +  		}  		else  		{ @@ -10303,14 +10313,24 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		gGL.pushMatrix();  		gGL.loadIdentity(); -		static const F32 clip_plane = 0.99999f; +		static const F32 clip_plane = 0.999f;  		if (LLGLSLShader::sNoFixedFunction)  		{ -			gUIProgram.bind(); +			gDebugProgram.bind();  		} -		gGL.color4ub(64,64,64,255); + +		if (LLMuteList::getInstance()->isMuted(avatar->getID())) +		{ //grey muted avatar +			gGL.diffuseColor4ub(64,64,64,255); +		} +		else +		{ //blue visually muted avatar +			gGL.diffuseColor4ub(72,61,139,255); +		} + +		{  		gGL.begin(LLRender::QUADS);  		gGL.vertex3f(-1, -1, clip_plane);  		gGL.vertex3f(1, -1, clip_plane); @@ -10318,10 +10338,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		gGL.vertex3f(-1, 1, clip_plane);  		gGL.end();  		gGL.flush(); +		}  		if (LLGLSLShader::sNoFixedFunction)  		{ -			gUIProgram.unbind(); +			gDebugProgram.unbind();  		}  		gGL.popMatrix(); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 832e05a06f..fb530ef22d 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -203,6 +203,45 @@ Message Template [PATH] not found.    </notification>    <notification +   icon="notify.tga" +   name="ExceededHighDetailRenderCost" +   persist="false" +   type="alertmodal"> +    Your avatar has become too complex to be rendered by even high performance computers.  Almost all Residents will see a low detail stand in instead of your actual avatar. +    <unique/> +    <usetemplate +     ignoretext="Avatar exceeded high detail complexity." +     name="okignore" +     yestext="Close"/> +  </notification> + +  <notification +   icon="notify.tga" +   name="ExceededMidDetailRenderCost" +   persist="false" +   type="alertmodal"> +    Your avatar has become too complex to be rendered by most computers.  Many Residents will see a low detail stand in instead of your actual avatar. +  <unique/> +  <usetemplate +   ignoretext="Avatar exceeded mid detail complexity." +   name="okignore" +   yestext="Close"/> +</notification> + +  <notification + icon="notify.tga" + name="ExceededLowDetailRenderCost" + persist="false" + type="alertmodal"> +    Your avatar has become too complex to be rendered by some computers.  Some Residents will see a low detail stand in instead of your actual avatar. +  <unique/> +  <usetemplate +   ignoretext="Avatar exceeded low detail complexity." +   name="okignore" +   yestext="Close"/> +  </notification> + +  <notification     icon="alertmodal.tga"     name="WearableSave"     type="alertmodal"> @@ -9935,5 +9974,5 @@ An internal error prevented us from properly updating your viewer.  The L$ balan     <tag>fail</tag>  Cannot create large prims that intersect other players.  Please re-try when other players have moved.    </notification> - +    </notifications> | 
