diff options
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 27 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolalpha.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llface.cpp | 1164 | ||||
| -rw-r--r-- | indra/newview/llface.h | 2 | ||||
| -rwxr-xr-x | indra/newview/llfloatermodelpreview.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.cpp | 40 | ||||
| -rw-r--r-- | indra/newview/llviewerdisplay.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.cpp | 113 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.h | 11 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llvoavatarself.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llvopartgroup.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 24 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 90 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 5 | 
15 files changed, 999 insertions, 499 deletions
| diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index bd109120cf..8cb456b4fd 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9162,7 +9162,7 @@      <key>RenderUseVAO</key>      <map>        <key>Comment</key> -      <string>Use GL Vertex Array Objects</string> +      <string>[EXPERIMENTAL] Use GL Vertex Array Objects</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -9170,7 +9170,19 @@        <key>Value</key>        <integer>0</integer>      </map> -    <key>RenderVBOMappingDisable</key> +  <key>RenderUseTransformFeedback</key> +  <map> +    <key>Comment</key> +    <string>[EXPERIMENTAL] Use transform feedback shaders for LoD updates</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map> + +  <key>RenderVBOMappingDisable</key>      <map>        <key>Comment</key>        <string>Disable VBO glMapBufferARB</string> @@ -12140,6 +12152,17 @@        <key>Value</key>        <integer>1</integer>      </map> +  <key>RenderSynchronousOcclusion</key> +  <map> +    <key>Comment</key> +    <string>Don't let occlusion queries get more than one frame behind (block until they complete).</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map>      <key>RenderDelayVBUpdate</key>      <map>        <key>Comment</key> diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5b62dbc560..a56e71baa8 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -405,6 +405,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  			{  				LLDrawInfo& params = **k; +				if ((params.mVertexBuffer->getTypeMask() & mask) != mask) +				{ //FIXME! +					//llwarns << "Missing required components, skipping render batch." << llendl; +					continue; +				} +  				LLRenderPass::applyModelMatrix(params); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 97b832520d..2824b1a32d 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -50,6 +50,8 @@  #include "pipeline.h"  #include "llviewerregion.h"  #include "llviewerwindow.h" +#include "llviewershadermgr.h" +  #define LL_MAX_INDICES_COUNT 1000000 @@ -57,7 +59,6 @@ BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE  #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) -  /*  For each vertex, given:  	B - binormal @@ -1111,6 +1112,73 @@ bool LLFace::canRenderAsMask()  } +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_VOLUME("Volume VB Cache"); + +//static  +void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) +{ +	LLFastTimer t(FTM_FACE_GEOM_VOLUME); +	U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | +				LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL; +	 +	if (vf.mWeights) +	{ +		mask |= LLVertexBuffer::MAP_WEIGHT4; +	} + +	LLVertexBuffer* buff = new LLVertexBuffer(mask, GL_STATIC_DRAW_ARB); +	vf.mVertexBuffer = buff; + +	buff->allocateBuffer(vf.mNumVertices, 0, true); + +	LLStrider<LLVector4a> f_vert; +	LLStrider<LLVector3> f_binorm; +	LLStrider<LLVector3> f_norm; +	LLStrider<LLVector2> f_tc; + +	buff->getBinormalStrider(f_binorm); +	buff->getVertexStrider(f_vert); +	buff->getNormalStrider(f_norm); +	buff->getTexCoord0Strider(f_tc); + +	for (U32 i = 0; i < vf.mNumVertices; ++i) +	{ +		*f_vert++ = vf.mPositions[i]; +		(*f_binorm++).set(vf.mBinormals[i].getF32ptr()); +		*f_tc++ = vf.mTexCoords[i]; +		(*f_norm++).set(vf.mNormals[i].getF32ptr()); +	} + +	if (vf.mWeights) +	{ +		LLStrider<LLVector4> f_wght; +		buff->getWeight4Strider(f_wght); +		for (U32 i = 0; i < vf.mNumVertices; ++i) +		{ +			(*f_wght++).set(vf.mWeights[i].getF32ptr()); +		} +	} + +	buff->flush(); +} + +//helper function for pushing primitives for transform shaders and cleaning up +//uninitialized data on the tail, plus tracking number of expected primitives +void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) +{ +	if (source_count > 0 && dest_count >= source_count) //protect against possible U32 wrapping +	{ +		//push source primitives +		buff->drawArrays(LLRender::POINTS, 0, source_count); +		U32 tail = dest_count-source_count; +		for (U32 i = 0; i < tail; ++i) +		{ //copy last source primitive into each element in tail +			buff->drawArrays(LLRender::POINTS, source_count-1, 1); +		} +		gPipeline.mTransformFeedbackPrimitives += dest_count; +	} +} +  static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal"); @@ -1128,7 +1196,6 @@ static LLFastTimer::DeclareTimer FTM_FACE_TEX_DEFAULT("Default");  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK("Quick");  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_NO_XFORM("No Xform");  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_XFORM("Xform"); -  static LLFastTimer::DeclareTimer FTM_FACE_TEX_QUICK_PLANAR("Quick Planar");  BOOL LLFace::getGeometryVolume(const LLVolume& volume, @@ -1301,17 +1368,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	LLMatrix4a mat_normal;  	mat_normal.loadu(mat_norm_in); -	//if it's not fullbright and has no normals, bake sunlight based on face normal -	//bool bake_sunlight = !getTextureEntry()->getFullbright() && -	//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); -  	F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; - +	bool do_xform = false;  	if (rebuild_tcoord)  	{ -		LLFastTimer t(FTM_FACE_GEOM_TEXTURE); -		bool do_xform; -			  		if (tep)  		{  			r  = tep->getRotation(); @@ -1340,599 +1400,757 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		{  			do_xform = false;  		} +	} +	 +	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +	if (use_transform_feedback && +		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 + +		LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); + +		if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) +		{ +			mVObjp->getVolume()->genBinormals(f); +			LLFace::cacheFaceInVRAM(vf); +			buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); +		}		 + +		LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr; +		 +		gGL.pushMatrix(); +		gGL.loadMatrix((GLfloat*) mat_vert_in.mMatrix); + +		if (rebuild_pos) +		{ +			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			gTransformPositionProgram.bind(); + +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); + +			U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + +			S32 val = 0.f; +			U8* vp = (U8*) &val; +			vp[0] = index; +			vp[1] = 0; +			vp[2] = 0; +			vp[3] = 0; +			 +			gTransformPositionProgram.uniform1i("texture_index_in", val); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + +			push_for_transform(buff, vf.mNumVertices, mGeomCount); + +			glEndTransformFeedback(); +		} + +		if (rebuild_color) +		{ +			LLFastTimer t(FTM_FACE_GEOM_COLOR); +			gTransformColorProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); + +			S32 val = *((S32*) color.mV); + +			gTransformColorProgram.uniform1i("color_in", val); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); +		} + +		if (rebuild_emissive) +		{ +			LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); +			gTransformColorProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); + +			U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + +			S32 glow32 = glow | +						 (glow << 8) | +						 (glow << 16) | +						 (glow << 24); + +			gTransformColorProgram.uniform1i("color_in", glow32); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); +		} + +		if (rebuild_normal) +		{ +			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			gTransformNormalProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); -		//bump setup -		LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); -		LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); -		LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_NORMAL); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); +		} -		LLQuaternion bump_quat; -		if (mDrawablep->isActive()) +		if (rebuild_binormal)  		{ -			bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); +			LLFastTimer t(FTM_FACE_GEOM_BINORMAL); +			gTransformBinormalProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount); +						 +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_BINORMAL); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback();  		} -		 -		if (bump_code) + +		if (rebuild_tcoord)  		{ -			mVObjp->getVolume()->genBinormals(f); -			F32 offset_multiple;  -			switch( bump_code ) -			{ -				case BE_NO_BUMP: -				offset_multiple = 0.f; -				break; -				case BE_BRIGHTNESS: -				case BE_DARKNESS: -				if( mTexture.notNull() && mTexture->hasGLTexture()) -				{ -					// Offset by approximately one texel -					S32 cur_discard = mTexture->getDiscardLevel(); -					S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); -					max_size <<= cur_discard; -					const F32 ARTIFICIAL_OFFSET = 2.f; -					offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; -				} -				else -				{ -					offset_multiple = 1.f/256; -				} -				break; +			LLFastTimer t(FTM_FACE_GEOM_TEXTURE); +			gTransformTexCoordProgram.bind(); +			 +			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); +						 +			glBeginTransformFeedback(GL_POINTS); +			buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); +			push_for_transform(buff, vf.mNumVertices, mGeomCount); +			glEndTransformFeedback(); -				default:  // Standard bumpmap textures.  Assumed to be 256x256 -				offset_multiple = 1.f / 256; -				break; -			} +			bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); -			F32 s_scale = 1.f; -			F32 t_scale = 1.f; -			if( tep ) +			if (do_bump)  			{ -				tep->getScale( &s_scale, &t_scale ); -			} -			// Use the nudged south when coming from above sun angle, such -			// that emboss mapping always shows up on the upward faces of cubes when  -			// it's noon (since a lot of builders build with the sun forced to noon). -			LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir; -			LLVector3   moon_ray = gSky.getMoonDirection(); -			LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - -			bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); -			bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); +				mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount); +				glBeginTransformFeedback(GL_POINTS); +				buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0); +				push_for_transform(buff, vf.mNumVertices, mGeomCount); +				glEndTransformFeedback(); +			}				  		} -		U8 texgen = getTextureEntry()->getTexGen(); -		if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) -		{ //planar texgen needs binormals -			mVObjp->getVolume()->genBinormals(f); +		glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + +		gGL.popMatrix(); + +		if (cur_shader) +		{ +			cur_shader->bind();  		} +	} +	else +	{ +		//if it's not fullbright and has no normals, bake sunlight based on face normal +		//bool bake_sunlight = !getTextureEntry()->getFullbright() && +		//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); -		U8 tex_mode = 0; -	 -		if (isState(TEXTURE_ANIM)) +		if (rebuild_tcoord)  		{ -			LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	 -			tex_mode = vobj->mTexAnimMode; +			LLFastTimer t(FTM_FACE_GEOM_TEXTURE); +									 +			//bump setup +			LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); +			LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); +			LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); -			if (!tex_mode) +			LLQuaternion bump_quat; +			if (mDrawablep->isActive())  			{ -				clearState(TEXTURE_ANIM); +				bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());  			} -			else +		 +			if (bump_code)  			{ -				os = ot = 0.f; -				r = 0.f; -				cos_ang = 1.f; -				sin_ang = 0.f; -				ms = mt = 1.f; +				mVObjp->getVolume()->genBinormals(f); +				F32 offset_multiple;  +				switch( bump_code ) +				{ +					case BE_NO_BUMP: +					offset_multiple = 0.f; +					break; +					case BE_BRIGHTNESS: +					case BE_DARKNESS: +					if( mTexture.notNull() && mTexture->hasGLTexture()) +					{ +						// Offset by approximately one texel +						S32 cur_discard = mTexture->getDiscardLevel(); +						S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); +						max_size <<= cur_discard; +						const F32 ARTIFICIAL_OFFSET = 2.f; +						offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; +					} +					else +					{ +						offset_multiple = 1.f/256; +					} +					break; -				do_xform = false; +					default:  // Standard bumpmap textures.  Assumed to be 256x256 +					offset_multiple = 1.f / 256; +					break; +				} + +				F32 s_scale = 1.f; +				F32 t_scale = 1.f; +				if( tep ) +				{ +					tep->getScale( &s_scale, &t_scale ); +				} +				// Use the nudged south when coming from above sun angle, such +				// that emboss mapping always shows up on the upward faces of cubes when  +				// it's noon (since a lot of builders build with the sun forced to noon). +				LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir; +				LLVector3   moon_ray = gSky.getMoonDirection(); +				LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + +				bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); +				bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);  			} -			if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) -			{ //don't override texture transform during tc bake -				tex_mode = 0; +			U8 texgen = getTextureEntry()->getTexGen(); +			if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) +			{ //planar texgen needs binormals +				mVObjp->getVolume()->genBinormals(f);  			} -		} -		LLVector4a scalea; -		scalea.load3(scale.mV); +			U8 tex_mode = 0; +	 +			if (isState(TEXTURE_ANIM)) +			{ +				LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	 +				tex_mode = vobj->mTexAnimMode; + +				if (!tex_mode) +				{ +					clearState(TEXTURE_ANIM); +				} +				else +				{ +					os = ot = 0.f; +					r = 0.f; +					cos_ang = 1.f; +					sin_ang = 0.f; +					ms = mt = 1.f; -		bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); -		bool do_tex_mat = tex_mode && mTextureMatrix; +					do_xform = false; +				} -		if (!in_atlas && !do_bump) -		{ //not in atlas or not bump mapped, might be able to do a cheap update -			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); +				if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) +				{ //don't override texture transform during tc bake +					tex_mode = 0; +				} +			} -			if (texgen != LLTextureEntry::TEX_GEN_PLANAR) -			{ -				LLFastTimer t(FTM_FACE_TEX_QUICK); -				if (!do_tex_mat) +			LLVector4a scalea; +			scalea.load3(scale.mV); + +			bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); +			bool do_tex_mat = tex_mode && mTextureMatrix; + +			if (!in_atlas && !do_bump) +			{ //not in atlas or not bump mapped, might be able to do a cheap update +				mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + +				if (texgen != LLTextureEntry::TEX_GEN_PLANAR)  				{ -					if (!do_xform) +					LLFastTimer t(FTM_FACE_TEX_QUICK); +					if (!do_tex_mat)  					{ -						LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); -						LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); -					} -					else -					{ -						LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); -						F32* dst = (F32*) tex_coords.get(); -						LLVector4a* src = (LLVector4a*) vf.mTexCoords; +						if (!do_xform) +						{ +							LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); +							LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); +						} +						else +						{ +							LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM); +							F32* dst = (F32*) tex_coords.get(); +							LLVector4a* src = (LLVector4a*) vf.mTexCoords; -						LLVector4a trans; -						trans.splat(-0.5f); +							LLVector4a trans; +							trans.splat(-0.5f); -						LLVector4a rot0; -						rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); +							LLVector4a rot0; +							rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); -						LLVector4a rot1; -						rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); +							LLVector4a rot1; +							rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); -						LLVector4a scale; -						scale.set(ms, mt, ms, mt); +							LLVector4a scale; +							scale.set(ms, mt, ms, mt); -						LLVector4a offset; -						offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); +							LLVector4a offset; +							offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); -						LLVector4Logical mask; -						mask.clear(); -						mask.setElement<2>(); -						mask.setElement<3>(); +							LLVector4Logical mask; +							mask.clear(); +							mask.setElement<2>(); +							mask.setElement<3>(); -						U32 count = num_vertices/2 + num_vertices%2; +							U32 count = num_vertices/2 + num_vertices%2; -						for (S32 i = 0; i < count; i++) +							for (S32 i = 0; i < count; i++) +							{	 +								LLVector4a res = *src++; +								xform4a(res, trans, mask, rot0, rot1, offset, scale); +								res.store4a(dst); +								dst += 4; +							} +						} +					} +					else +					{ //do tex mat, no texgen, no atlas, no bump +						for (S32 i = 0; i < num_vertices; i++)  						{	 -							LLVector4a res = *src++; -							xform4a(res, trans, mask, rot0, rot1, offset, scale); -							res.store4a(dst); -							dst += 4; +							LLVector2 tc(vf.mTexCoords[i]); +							//LLVector4a& norm = vf.mNormals[i]; +							//LLVector4a& center = *(vf.mCenter); + +							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); +							tmp = tmp * *mTextureMatrix; +							tc.mV[0] = tmp.mV[0]; +							tc.mV[1] = tmp.mV[1]; +							*tex_coords++ = tc;	  						}  					}  				}  				else -				{ //do tex mat, no texgen, no atlas, no bump -					for (S32 i = 0; i < num_vertices; i++) -					{	 -						LLVector2 tc(vf.mTexCoords[i]); -						//LLVector4a& norm = vf.mNormals[i]; -						//LLVector4a& center = *(vf.mCenter); - -						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); -						tmp = tmp * *mTextureMatrix; -						tc.mV[0] = tmp.mV[0]; -						tc.mV[1] = tmp.mV[1]; -						*tex_coords++ = tc;	 -					} -				} -			} -			else -			{ //no bump, no atlas, tex gen planar -				LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); -				if (do_tex_mat) -				{ -					for (S32 i = 0; i < num_vertices; i++) -					{	 -						LLVector2 tc(vf.mTexCoords[i]); -						LLVector4a& norm = vf.mNormals[i]; -						LLVector4a& center = *(vf.mCenter); -						LLVector4a vec = vf.mPositions[i];	 -						vec.mul(scalea); -						planarProjection(tc, norm, center, vec); +				{ //no bump, no atlas, tex gen planar +					LLFastTimer t(FTM_FACE_TEX_QUICK_PLANAR); +					if (do_tex_mat) +					{ +						for (S32 i = 0; i < num_vertices; i++) +						{	 +							LLVector2 tc(vf.mTexCoords[i]); +							LLVector4a& norm = vf.mNormals[i]; +							LLVector4a& center = *(vf.mCenter); +							LLVector4a vec = vf.mPositions[i];	 +							vec.mul(scalea); +							planarProjection(tc, norm, center, vec); -						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); -						tmp = tmp * *mTextureMatrix; -						tc.mV[0] = tmp.mV[0]; -						tc.mV[1] = tmp.mV[1]; +							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); +							tmp = tmp * *mTextureMatrix; +							tc.mV[0] = tmp.mV[0]; +							tc.mV[1] = tmp.mV[1]; -						*tex_coords++ = tc;	 +							*tex_coords++ = tc;	 +						}  					} -				} -				else -				{ -					for (S32 i = 0; i < num_vertices; i++) -					{	 -						LLVector2 tc(vf.mTexCoords[i]); -						LLVector4a& norm = vf.mNormals[i]; -						LLVector4a& center = *(vf.mCenter); -						LLVector4a vec = vf.mPositions[i];	 -						vec.mul(scalea); -						planarProjection(tc, norm, center, vec); +					else +					{ +						for (S32 i = 0; i < num_vertices; i++) +						{	 +							LLVector2 tc(vf.mTexCoords[i]); +							LLVector4a& norm = vf.mNormals[i]; +							LLVector4a& center = *(vf.mCenter); +							LLVector4a vec = vf.mPositions[i];	 +							vec.mul(scalea); +							planarProjection(tc, norm, center, vec); -						xform(tc, cos_ang, sin_ang, os, ot, ms, mt); +							xform(tc, cos_ang, sin_ang, os, ot, ms, mt); -						*tex_coords++ = tc;	 +							*tex_coords++ = tc;	 +						}  					}  				} -			} -			if (map_range) -			{ -				mVertexBuffer->flush(); +				if (map_range) +				{ +					mVertexBuffer->flush(); +				}  			} -		} -		else -		{ //either bump mapped or in atlas, just do the whole expensive loop -			LLFastTimer t(FTM_FACE_TEX_DEFAULT); -			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); +			else +			{ //either bump mapped or in atlas, just do the whole expensive loop +				LLFastTimer t(FTM_FACE_TEX_DEFAULT); +				mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range); -			std::vector<LLVector2> bump_tc; +				std::vector<LLVector2> bump_tc; -			for (S32 i = 0; i < num_vertices; i++) -			{	 -				LLVector2 tc(vf.mTexCoords[i]); +				for (S32 i = 0; i < num_vertices; i++) +				{	 +					LLVector2 tc(vf.mTexCoords[i]); -				LLVector4a& norm = vf.mNormals[i]; +					LLVector4a& norm = vf.mNormals[i]; -				LLVector4a& center = *(vf.mCenter); +					LLVector4a& center = *(vf.mCenter); -				if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) -				{ -					LLVector4a vec = vf.mPositions[i]; +					if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) +					{ +						LLVector4a vec = vf.mPositions[i]; -					vec.mul(scalea); +						vec.mul(scalea); + +						switch (texgen) +						{ +							case LLTextureEntry::TEX_GEN_PLANAR: +								planarProjection(tc, norm, center, vec); +								break; +							case LLTextureEntry::TEX_GEN_SPHERICAL: +								sphericalProjection(tc, norm, center, vec); +								break; +							case LLTextureEntry::TEX_GEN_CYLINDRICAL: +								cylindricalProjection(tc, norm, center, vec); +								break; +							default: +								break; +						}		 +					} -					switch (texgen) +					if (tex_mode && mTextureMatrix)  					{ -						case LLTextureEntry::TEX_GEN_PLANAR: -							planarProjection(tc, norm, center, vec); +						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); +						tmp = tmp * *mTextureMatrix; +						tc.mV[0] = tmp.mV[0]; +						tc.mV[1] = tmp.mV[1]; +					} +					else +					{ +						xform(tc, cos_ang, sin_ang, os, ot, ms, mt); +					} + +					if(in_atlas) +					{ +						// +						//manually calculate tex-coord per vertex for varying address modes. +						//should be removed if shader can handle this. +						// + +						S32 int_part = 0 ; +						switch(mTexture->getAddressMode()) +						{ +						case LLTexUnit::TAM_CLAMP: +							if(tc.mV[0] < 0.f) +							{ +								tc.mV[0] = 0.f ; +							} +							else if(tc.mV[0] > 1.f) +							{ +								tc.mV[0] = 1.f; +							} + +							if(tc.mV[1] < 0.f) +							{ +								tc.mV[1] = 0.f ; +							} +							else if(tc.mV[1] > 1.f) +							{ +								tc.mV[1] = 1.f; +							}  							break; -						case LLTextureEntry::TEX_GEN_SPHERICAL: -							sphericalProjection(tc, norm, center, vec); +						case LLTexUnit::TAM_MIRROR: +							if(tc.mV[0] < 0.f) +							{ +								tc.mV[0] = -tc.mV[0] ; +							} +							int_part = (S32)tc.mV[0] ; +							if(int_part & 1) //odd number +							{ +								tc.mV[0] = int_part + 1 - tc.mV[0] ; +							} +							else //even number +							{ +								tc.mV[0] -= int_part ; +							} + +							if(tc.mV[1] < 0.f) +							{ +								tc.mV[1] = -tc.mV[1] ; +							} +							int_part = (S32)tc.mV[1] ; +							if(int_part & 1) //odd number +							{ +								tc.mV[1] = int_part + 1 - tc.mV[1] ; +							} +							else //even number +							{ +								tc.mV[1] -= int_part ; +							}  							break; -						case LLTextureEntry::TEX_GEN_CYLINDRICAL: -							cylindricalProjection(tc, norm, center, vec); +						case LLTexUnit::TAM_WRAP: +							if(tc.mV[0] > 1.f) +								tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; +							else if(tc.mV[0] < -1.f) +								tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; + +							if(tc.mV[1] > 1.f) +								tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; +							else if(tc.mV[1] < -1.f) +								tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; + +							if(tc.mV[0] < 0.f) +							{ +								tc.mV[0] = 1.0f + tc.mV[0] ; +							} +							if(tc.mV[1] < 0.f) +							{ +								tc.mV[1] = 1.0f + tc.mV[1] ; +							}  							break;  						default:  							break; -					}		 -				} +						} +				 +						tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; +						tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; +					} +				 -				if (tex_mode && mTextureMatrix) -				{ -					LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); -					tmp = tmp * *mTextureMatrix; -					tc.mV[0] = tmp.mV[0]; -					tc.mV[1] = tmp.mV[1]; +					*tex_coords++ = tc; +					if (do_bump) +					{ +						bump_tc.push_back(tc); +					}  				} -				else + +				if (map_range)  				{ -					xform(tc, cos_ang, sin_ang, os, ot, ms, mt); +					mVertexBuffer->flush();  				} -				if(in_atlas) +				if (do_bump)  				{ -					// -					//manually calculate tex-coord per vertex for varying address modes. -					//should be removed if shader can handle this. -					// - -					S32 int_part = 0 ; -					switch(mTexture->getAddressMode()) +					mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); +		 +					for (S32 i = 0; i < num_vertices; i++)  					{ -					case LLTexUnit::TAM_CLAMP: -						if(tc.mV[0] < 0.f) -						{ -							tc.mV[0] = 0.f ; -						} -						else if(tc.mV[0] > 1.f) -						{ -							tc.mV[0] = 1.f; -						} - -						if(tc.mV[1] < 0.f) -						{ -							tc.mV[1] = 0.f ; -						} -						else if(tc.mV[1] > 1.f) -						{ -							tc.mV[1] = 1.f; -						} -						break; -					case LLTexUnit::TAM_MIRROR: -						if(tc.mV[0] < 0.f) -						{ -							tc.mV[0] = -tc.mV[0] ; -						} -						int_part = (S32)tc.mV[0] ; -						if(int_part & 1) //odd number -						{ -							tc.mV[0] = int_part + 1 - tc.mV[0] ; -						} -						else //even number +						LLVector4a tangent; +						tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); + +						LLMatrix4a tangent_to_object; +						tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); +						LLVector4a t; +						tangent_to_object.rotate(binormal_dir, t); +						LLVector4a binormal; +						mat_normal.rotate(t, binormal); +						 +						//VECTORIZE THIS +						if (mDrawablep->isActive())  						{ -							tc.mV[0] -= int_part ; +							LLVector3 t; +							t.set(binormal.getF32ptr()); +							t *= bump_quat; +							binormal.load3(t.mV);  						} -						if(tc.mV[1] < 0.f) -						{ -							tc.mV[1] = -tc.mV[1] ; -						} -						int_part = (S32)tc.mV[1] ; -						if(int_part & 1) //odd number -						{ -							tc.mV[1] = int_part + 1 - tc.mV[1] ; -						} -						else //even number -						{ -							tc.mV[1] -= int_part ; -						} -						break; -					case LLTexUnit::TAM_WRAP: -						if(tc.mV[0] > 1.f) -							tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; -						else if(tc.mV[0] < -1.f) -							tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; - -						if(tc.mV[1] > 1.f) -							tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; -						else if(tc.mV[1] < -1.f) -							tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; - -						if(tc.mV[0] < 0.f) -						{ -							tc.mV[0] = 1.0f + tc.mV[0] ; -						} -						if(tc.mV[1] < 0.f) -						{ -							tc.mV[1] = 1.0f + tc.mV[1] ; -						} -						break; -					default: -						break; +						binormal.normalize3fast(); +						LLVector2 tc = bump_tc[i]; +						tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); +					 +						*tex_coords2++ = tc;  					} -				 -					tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; -					tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; -				} -				 - -				*tex_coords++ = tc; -				if (do_bump) -				{ -					bump_tc.push_back(tc); -				} -			} - -			if (map_range) -			{ -				mVertexBuffer->flush(); -			} -			if (do_bump) -			{ -				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range); -		 -				for (S32 i = 0; i < num_vertices; i++) -				{ -					LLVector4a tangent; -					tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); - -					LLMatrix4a tangent_to_object; -					tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); -					LLVector4a t; -					tangent_to_object.rotate(binormal_dir, t); -					LLVector4a binormal; -					mat_normal.rotate(t, binormal); -						 -					//VECTORIZE THIS -					if (mDrawablep->isActive()) +					if (map_range)  					{ -						LLVector3 t; -						t.set(binormal.getF32ptr()); -						t *= bump_quat; -						binormal.load3(t.mV); +						mVertexBuffer->flush();  					} - -					binormal.normalize3fast(); -					LLVector2 tc = bump_tc[i]; -					tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); -					 -					*tex_coords2++ = tc; -				} - -				if (map_range) -				{ -					mVertexBuffer->flush();  				}  			}  		} -	} -	if (rebuild_pos) -	{ -		LLFastTimer t(FTM_FACE_GEOM_POSITION); -		llassert(num_vertices > 0); +		if (rebuild_pos) +		{ +			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			llassert(num_vertices > 0); -		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); +			mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); -		LLMatrix4a mat_vert; -		mat_vert.loadu(mat_vert_in); +			LLMatrix4a mat_vert; +			mat_vert.loadu(mat_vert_in); -		LLVector4a* src = vf.mPositions; -		volatile F32* dst = (volatile F32*) vert.get(); +			LLVector4a* src = vf.mPositions; +			volatile F32* dst = (volatile F32*) vert.get(); -		volatile F32* end = dst+num_vertices*4; -		LLVector4a res; +			volatile F32* end = dst+num_vertices*4; +			LLVector4a res; -		LLVector4a texIdx; +			LLVector4a texIdx; -		U8 index = mTextureIndex < 255 ? mTextureIndex : 0; +			U8 index = mTextureIndex < 255 ? mTextureIndex : 0; -		F32 val = 0.f; -		U8* vp = (U8*) &val; -		vp[0] = index; -		vp[1] = 0; -		vp[2] = 0; -		vp[3] = 0; +			F32 val = 0.f; +			U8* vp = (U8*) &val; +			vp[0] = index; +			vp[1] = 0; +			vp[2] = 0; +			vp[3] = 0; -		llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); +			llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); -		LLVector4Logical mask; -		mask.clear(); -		mask.setElement<3>(); +			LLVector4Logical mask; +			mask.clear(); +			mask.setElement<3>(); -		texIdx.set(0,0,0,val); - -		{ -			LLFastTimer t(FTM_FACE_POSITION_STORE); -			LLVector4a tmp; +			texIdx.set(0,0,0,val); -			do -			{	 -				mat_vert.affineTransform(*src++, res); -				tmp.setSelectWithMask(mask, texIdx, res); -				tmp.store4a((F32*) dst); -				dst += 4; +			{ +				LLFastTimer t(FTM_FACE_POSITION_STORE); +				LLVector4a tmp; + +				do +				{	 +					mat_vert.affineTransform(*src++, res); +					tmp.setSelectWithMask(mask, texIdx, res); +					tmp.store4a((F32*) dst); +					dst += 4; +				} +				while(dst < end);  			} -			while(dst < end); -		} -		{ -			LLFastTimer t(FTM_FACE_POSITION_PAD); -			S32 aligned_pad_vertices = mGeomCount - num_vertices; -			res.set(res[0], res[1], res[2], 0.f); +			{ +				LLFastTimer t(FTM_FACE_POSITION_PAD); +				S32 aligned_pad_vertices = mGeomCount - num_vertices; +				res.set(res[0], res[1], res[2], 0.f); + +				while (aligned_pad_vertices > 0) +				{ +					--aligned_pad_vertices; +					res.store4a((F32*) dst); +					dst += 4; +				} +			} -			while (aligned_pad_vertices > 0) +			if (map_range)  			{ -				--aligned_pad_vertices; -				res.store4a((F32*) dst); -				dst += 4; +				mVertexBuffer->flush();  			}  		} -		if (map_range) -		{ -			mVertexBuffer->flush(); -		} -	} -	if (rebuild_normal) -	{ -		LLFastTimer t(FTM_FACE_GEOM_NORMAL); -		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); -		F32* normals = (F32*) norm.get(); +		if (rebuild_normal) +		{ +			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); +			F32* normals = (F32*) norm.get(); -		for (S32 i = 0; i < num_vertices; i++) -		{	 -			LLVector4a normal; -			mat_normal.rotate(vf.mNormals[i], normal); -			normal.normalize3fast(); -			normal.store4a(normals); -			normals += 4; -		} +			for (S32 i = 0; i < num_vertices; i++) +			{	 +				LLVector4a normal; +				mat_normal.rotate(vf.mNormals[i], normal); +				normal.normalize3fast(); +				normal.store4a(normals); +				normals += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_binormal) -	{ -		LLFastTimer t(FTM_FACE_GEOM_BINORMAL); -		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); -		F32* binormals = (F32*) binorm.get(); +		if (rebuild_binormal) +		{ +			LLFastTimer t(FTM_FACE_GEOM_BINORMAL); +			mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); +			F32* binormals = (F32*) binorm.get(); -		for (S32 i = 0; i < num_vertices; i++) -		{	 -			LLVector4a binormal; -			mat_normal.rotate(vf.mBinormals[i], binormal); -			binormal.normalize3fast(); -			binormal.store4a(binormals); -			binormals += 4; -		} +			for (S32 i = 0; i < num_vertices; i++) +			{	 +				LLVector4a binormal; +				mat_normal.rotate(vf.mBinormals[i], binormal); +				binormal.normalize3fast(); +				binormal.store4a(binormals); +				binormals += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_weights && vf.mWeights) -	{ -		LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); -		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); -		F32* weights = (F32*) wght.get(); -		LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); -		if (map_range) +		if (rebuild_weights && vf.mWeights)  		{ -			mVertexBuffer->flush(); +			LLFastTimer t(FTM_FACE_GEOM_WEIGHTS); +			mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); +			F32* weights = (F32*) wght.get(); +			LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) -	{ -		LLFastTimer t(FTM_FACE_GEOM_COLOR); -		mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); +		if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) +		{ +			LLFastTimer t(FTM_FACE_GEOM_COLOR); +			mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); -		LLVector4a src; +			LLVector4a src; -		U32 vec[4]; -		vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; +			U32 vec[4]; +			vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; -		src.loadua((F32*) vec); +			src.loadua((F32*) vec); -		F32* dst = (F32*) colors.get(); -		S32 num_vecs = num_vertices/4; -		if (num_vertices%4 > 0) -		{ -			++num_vecs; -		} +			F32* dst = (F32*) colors.get(); +			S32 num_vecs = num_vertices/4; +			if (num_vertices%4 > 0) +			{ +				++num_vecs; +			} -		for (S32 i = 0; i < num_vecs; i++) -		{	 -			src.store4a(dst); -			dst += 4; -		} +			for (S32 i = 0; i < num_vecs; i++) +			{	 +				src.store4a(dst); +				dst += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		} -	} -	if (rebuild_emissive) -	{ -		LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); -		LLStrider<LLColor4U> emissive; -		mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); +		if (rebuild_emissive) +		{ +			LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); +			LLStrider<LLColor4U> emissive; +			mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); -		U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); +			U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); -		LLVector4a src; +			LLVector4a src; -		U32 glow32 = glow | -					 (glow << 8) | -					 (glow << 16) | -					 (glow << 24); +			U32 glow32 = glow | +						 (glow << 8) | +						 (glow << 16) | +						 (glow << 24); -		U32 vec[4]; -		vec[0] = vec[1] = vec[2] = vec[3] = glow32; +			U32 vec[4]; +			vec[0] = vec[1] = vec[2] = vec[3] = glow32; -		src.loadua((F32*) vec); +			src.loadua((F32*) vec); -		F32* dst = (F32*) emissive.get(); -		S32 num_vecs = num_vertices/4; -		if (num_vertices%4 > 0) -		{ -			++num_vecs; -		} +			F32* dst = (F32*) emissive.get(); +			S32 num_vecs = num_vertices/4; +			if (num_vertices%4 > 0) +			{ +				++num_vecs; +			} -		for (S32 i = 0; i < num_vecs; i++) -		{	 -			src.store4a(dst); -			dst += 4; -		} +			for (S32 i = 0; i < num_vecs; i++) +			{	 +				src.store4a(dst); +				dst += 4; +			} -		if (map_range) -		{ -			mVertexBuffer->flush(); +			if (map_range) +			{ +				mVertexBuffer->flush(); +			}  		}  	} +  	if (rebuild_tcoord)  	{  		mTexExtents[0].setVec(0,0); diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 82e4ab61b7..c31f357693 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -83,6 +83,8 @@ public:  	static void initClass(); +	static void cacheFaceInVRAM(const LLVolumeFace& vf); +  public:  	LLFace(LLDrawable* drawablep, LLViewerObject* objp)   { init(drawablep, objp); }  	~LLFace()  { destroy(); } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 7448f2bb2a..b362fa340c 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -540,7 +540,7 @@ LLFloaterModelPreview::~LLFloaterModelPreview()  	if (mGLName)  	{ -		LLImageGL::deleteTextures(1, &mGLName ); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, &mGLName );  	}  	delete mStatusLock; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e886f83671..06604fba6f 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -85,12 +85,32 @@ static F32 sCurMaxTexPriority = 1.f;  class LLOcclusionQueryPool : public LLGLNamePool  { +public: +	LLOcclusionQueryPool() +	{ +		mCurQuery = 1; +	} +  protected: + +	std::list<GLuint> mAvailableName; +	GLuint mCurQuery; +		  	virtual GLuint allocateName()  	{ -		GLuint name; -		glGenQueriesARB(1, &name); -		return name; +		GLuint ret = 0; + +		if (!mAvailableName.empty()) +		{ +			ret = mAvailableName.front(); +			mAvailableName.pop_front(); +		} +		else +		{ +			ret = mCurQuery++; +		} + +		return ret;  	}  	virtual void releaseName(GLuint name) @@ -98,7 +118,8 @@ protected:  #if LL_TRACK_PENDING_OCCLUSION_QUERIES  		LLSpatialGroup::sPendingQueries.erase(name);  #endif -		glDeleteQueriesARB(1, &name); +		llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); +		mAvailableName.push_back(name);  	}  }; @@ -687,6 +708,11 @@ void LLSpatialGroup::rebuildGeom()  	if (!isDead())  	{  		mSpatialPartition->rebuildGeom(this); + +		if (isState(LLSpatialGroup::MESH_DIRTY)) +		{ +			gPipeline.markMeshDirty(this); +		}  	}  } @@ -1587,7 +1613,7 @@ BOOL LLSpatialGroup::rebound()  }  static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait");  void LLSpatialGroup::checkOcclusion()  { @@ -1607,7 +1633,9 @@ void LLSpatialGroup::checkOcclusion()  			{  				glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); -				if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) +				static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); + +				if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)  				{ //query was issued last frame, wait until it's available  					S32 max_loop = 1024;  					LLFastTimer t(FTM_OCCLUSION_WAIT); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 001d8e184a..99ed04d1af 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -755,12 +755,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  				gTextureList.updateImages(max_image_decode_time);  			} -			{ +			/*{  				LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);  				//remove dead textures from GL  				LLImageGL::deleteDeadTextures();  				stop_glerror(); -			} +			}*/  		}  		LLGLState::checkStates(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 0473e2b7c0..485e3af62d 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,6 +63,13 @@ bool				LLViewerShaderMgr::sSkipReload = false;  LLVector4			gShinyOrigin; +//transform shaders +LLGLSLShader			gTransformPositionProgram; +LLGLSLShader			gTransformTexCoordProgram; +LLGLSLShader			gTransformNormalProgram; +LLGLSLShader			gTransformColorProgram; +LLGLSLShader			gTransformBinormalProgram; +  //utility shaders  LLGLSLShader	gOcclusionProgram;  LLGLSLShader	gCustomAlphaProgram; @@ -438,7 +445,8 @@ void LLViewerShaderMgr::setShaders()  		S32 wl_class = 2;  		S32 water_class = 2;  		S32 deferred_class = 0; -		 +		S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0; +  		if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&  		    gSavedSettings.getBOOL("RenderDeferred") &&  			gSavedSettings.getBOOL("RenderAvatarVP") && @@ -476,6 +484,7 @@ void LLViewerShaderMgr::setShaders()  			gSky.mVOSkyp->forceSkyUpdate();  		} +		  		// Load lighting shaders  		mVertexShaderLevel[SHADER_LIGHTING] = light_class;  		mVertexShaderLevel[SHADER_INTERFACE] = light_class; @@ -485,6 +494,7 @@ void LLViewerShaderMgr::setShaders()  		mVertexShaderLevel[SHADER_EFFECT] = effect_class;  		mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class;  		mVertexShaderLevel[SHADER_DEFERRED] = deferred_class; +		mVertexShaderLevel[SHADER_TRANSFORM] = transform_class;  		BOOL loaded = loadBasicShaders(); @@ -518,6 +528,11 @@ void LLViewerShaderMgr::setShaders()  			if (loaded)  			{ +				loaded = loadTransformShaders(); +			} + +			if (loaded) +			{  				// Load max avatar shaders to set the max level  				mVertexShaderLevel[SHADER_AVATAR] = 3;  				mMaxAvatarShaderLevel = 3; @@ -733,6 +748,12 @@ void LLViewerShaderMgr::unloadShaders()  	gDeferredSkinnedBumpProgram.unload();  	gDeferredSkinnedAlphaProgram.unload(); +	gTransformPositionProgram.unload(); +	gTransformTexCoordProgram.unload(); +	gTransformNormalProgram.unload(); +	gTransformColorProgram.unload(); +	gTransformBinormalProgram.unload(); +  	mVertexShaderLevel[SHADER_LIGHTING] = 0;  	mVertexShaderLevel[SHADER_OBJECT] = 0;  	mVertexShaderLevel[SHADER_AVATAR] = 0; @@ -741,6 +762,7 @@ void LLViewerShaderMgr::unloadShaders()  	mVertexShaderLevel[SHADER_INTERFACE] = 0;  	mVertexShaderLevel[SHADER_EFFECT] = 0;  	mVertexShaderLevel[SHADER_WINDLIGHT] = 0; +	mVertexShaderLevel[SHADER_TRANSFORM] = 0;  	gPipeline.mVertexShadersLoaded = 0;  } @@ -2763,6 +2785,95 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()  	return success;  } +BOOL LLViewerShaderMgr::loadTransformShaders() +{ +	BOOL success = TRUE; +	 +	if (mVertexShaderLevel[SHADER_TRANSFORM] < 1) +	{ +		gTransformPositionProgram.unload(); +		gTransformTexCoordProgram.unload(); +		gTransformNormalProgram.unload(); +		gTransformColorProgram.unload(); +		gTransformBinormalProgram.unload(); +		return TRUE; +	} + +	if (success) +	{ +		gTransformPositionProgram.mName = "Position Transform Shader"; +		gTransformPositionProgram.mShaderFiles.clear(); +		gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"position_out", +			"texture_index_out", +		}; +	 +		success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings); +	} + +	if (success) +	{ +		gTransformTexCoordProgram.mName = "TexCoord Transform Shader"; +		gTransformTexCoordProgram.mShaderFiles.clear(); +		gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"texcoord_out", +		}; +	 +		success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings); +	} + +	if (success) +	{ +		gTransformNormalProgram.mName = "Normal Transform Shader"; +		gTransformNormalProgram.mShaderFiles.clear(); +		gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"normal_out", +		}; +	 +		success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings); +	} + +	if (success) +	{ +		gTransformColorProgram.mName = "Color Transform Shader"; +		gTransformColorProgram.mShaderFiles.clear(); +		gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"color_out", +		}; +	 +		success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings); +	} + +	if (success) +	{ +		gTransformBinormalProgram.mName = "Binormal Transform Shader"; +		gTransformBinormalProgram.mShaderFiles.clear(); +		gTransformBinormalProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB)); +		gTransformBinormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM]; + +		const char* varyings[] = { +			"binormal_out", +		}; +	 +		success = gTransformBinormalProgram.createShader(NULL, NULL, 1, varyings); +	} + +	 +	return success; +} +  std::string LLViewerShaderMgr::getShaderDirPrefix(void)  {  	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index d10aba85c7..03d686e07e 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -54,6 +54,7 @@ public:  	BOOL loadShadersWater();  	BOOL loadShadersInterface();  	BOOL loadShadersWindLight(); +	BOOL loadTransformShaders();  	std::vector<S32> mVertexShaderLevel;  	S32	mMaxAvatarShaderLevel; @@ -69,6 +70,7 @@ public:  		SHADER_WINDLIGHT,  		SHADER_WATER,  		SHADER_DEFERRED, +		SHADER_TRANSFORM,  		SHADER_COUNT  	}; @@ -209,6 +211,15 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade  extern LLVector4			gShinyOrigin; +//transform shaders +extern LLGLSLShader			gTransformPositionProgram; +extern LLGLSLShader			gTransformTexCoordProgram; +extern LLGLSLShader			gTransformNormalProgram; +extern LLGLSLShader			gTransformColorProgram; +extern LLGLSLShader			gTransformBinormalProgram; + + +  //utility shaders  extern LLGLSLShader			gOcclusionProgram;  extern LLGLSLShader			gCustomAlphaProgram; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c221c7fdd8..083ad622cd 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -896,7 +896,7 @@ void LLVOAvatar::deleteLayerSetCaches(bool clearAll)  		}  		if (mBakedTextureDatas[i].mMaskTexName)  		{ -			glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); +			LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName));  			mBakedTextureDatas[i].mMaskTexName = 0 ;  		}  	} @@ -7394,7 +7394,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture  			}  			U32 gl_name; -			LLImageGL::generateTextures(1, &gl_name ); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, 1, &gl_name );  			stop_glerror();  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); @@ -7431,7 +7431,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture  						maskData->mLastDiscardLevel = discard_level;  						if (self->mBakedTextureDatas[baked_index].mMaskTexName)  						{ -							LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); +							LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));  						}  						self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;  						found_texture_id = true; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index f063653cc5..b6d4d6b56f 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2605,7 +2605,7 @@ void LLVOAvatarSelf::deleteScratchTextures()  		 namep;   		 namep = sScratchTexNames.getNextData() )  	{ -		LLImageGL::deleteTextures(1, (U32 *)namep ); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, (U32 *)namep );  		stop_glerror();  	} diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index b6adc776cc..fca97987a2 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -125,7 +125,7 @@ S32 LLVOPartGroup::findAvailableVBSlot()  void LLVOPartGroup::freeVBSlot(S32 idx)  {  	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); -	llassert(sVBSlotCursor > sVBSlotFree); +	//llassert(sVBSlotCursor > sVBSlotFree);  	if (sVBSlotCursor > sVBSlotFree)  	{ diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6d4565ec2f..6bb4e9e63b 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1089,9 +1089,33 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  			}  		} + +		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +		bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && +			(!mVolumeImpl || !mVolumeImpl->isVolumeUnique()); + +		if (cache_in_vram) +		{ //this volume might be used as source data for a transform object, put it in vram +			LLVolume* volume = getVolume(); +			for (S32 i = 0; i < volume->getNumFaces(); ++i) +			{ +				const LLVolumeFace& face = volume->getVolumeFace(i); +				if (face.mVertexBuffer.notNull()) +				{ //already cached +					break; +				} +				volume->genBinormals(i); +				LLFace::cacheFaceInVRAM(face); +			} +		} +		 +  		return TRUE;  	} + +  	return FALSE;  } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index a691302cb9..a76a32f834 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -51,6 +51,10 @@  // newview includes  #include "llagent.h"  #include "llagentcamera.h" +#include "llappviewer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h"  #include "lldrawable.h"  #include "lldrawpoolalpha.h"  #include "lldrawpoolavatar.h" @@ -403,9 +407,11 @@ LLPipeline::LLPipeline() :  	mInitialized(FALSE),  	mVertexShadersEnabled(FALSE),  	mVertexShadersLoaded(0), +	mTransformFeedbackPrimitives(0),  	mRenderDebugFeatureMask(0),  	mRenderDebugMask(0),  	mOldRenderDebugMask(0), +	mMeshDirtyQueryObject(0),  	mGroupQ1Locked(false),  	mGroupQ2Locked(false),  	mResetVertexBuffers(false), @@ -693,6 +699,12 @@ void LLPipeline::destroyGL()  	{  		LLVertexBuffer::sEnableVBOs = FALSE;  	} + +	if (mMeshDirtyQueryObject) +	{ +		glDeleteQueriesARB(1, &mMeshDirtyQueryObject); +		mMeshDirtyQueryObject = 0; +	}  }  static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); @@ -1028,19 +1040,19 @@ void LLPipeline::releaseGLBuffers()  	if (mNoiseMap)  	{ -		LLImageGL::deleteTextures(1, &mNoiseMap); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, &mNoiseMap);  		mNoiseMap = 0;  	}  	if (mTrueNoiseMap)  	{ -		LLImageGL::deleteTextures(1, &mTrueNoiseMap); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, &mTrueNoiseMap);  		mTrueNoiseMap = 0;  	}  	if (mLightFunc)  	{ -		LLImageGL::deleteTextures(1, &mLightFunc); +		LLImageGL::deleteTextures(LLTexUnit::TT_TEXTURE, 1, &mLightFunc);  		mLightFunc = 0;  	} @@ -1131,7 +1143,7 @@ void LLPipeline::createGLBuffers()  				noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;  			} -			LLImageGL::generateTextures(1, &mNoiseMap); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, 1, &mNoiseMap);  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);  			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); @@ -1147,7 +1159,7 @@ void LLPipeline::createGLBuffers()  				noise[i] = ll_frand()*2.0-1.0;  			} -			LLImageGL::generateTextures(1, &mTrueNoiseMap); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, 1, &mTrueNoiseMap);  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);  			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false);  			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); @@ -1183,7 +1195,7 @@ void LLPipeline::createGLBuffers()  				}  			} -			LLImageGL::generateTextures(1, &mLightFunc); +			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, 1, &mLightFunc);  			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);  			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg, false);  			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -2829,6 +2841,11 @@ void LLPipeline::processPartitionQ()  	mPartitionQ.clear();  } +void LLPipeline::markMeshDirty(LLSpatialGroup* group) +{ +	mMeshDirtyGroup.push_back(group); +} +  void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)  {  	LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -3437,15 +3454,43 @@ void LLPipeline::postSort(LLCamera& camera)  			}  		}  	} +	 +	//flush particle VB +	LLVOPartGroup::sVB->flush(); + +	/*bool use_transform_feedback = gTransformPositionProgram.mProgramObject && !mMeshDirtyGroup.empty(); + +	if (use_transform_feedback) +	{ //place a query around potential transform feedback code for synchronization +		mTransformFeedbackPrimitives = 0; + +		if (!mMeshDirtyQueryObject) +		{ +			glGenQueriesARB(1, &mMeshDirtyQueryObject); +		} + +		glBeginQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mMeshDirtyQueryObject); +	}*/ + +	//pack vertex buffers for groups that chose to delay their updates +	for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) +	{ +		(*iter)->rebuildMesh(); +	} + +	/*if (use_transform_feedback) +	{ +		glEndQueryARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); +	}*/ +	 +	mMeshDirtyGroup.clear(); +  	if (!sShadowRender)  	{  		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());  	} -	//flush particle VB -	LLVOPartGroup::sVB->flush(); -  	llpushcallstacks ;  	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus  	if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) @@ -3532,6 +3577,33 @@ void LLPipeline::postSort(LLCamera& camera)  		}  	} +	/*static LLFastTimer::DeclareTimer FTM_TRANSFORM_WAIT("Transform Fence"); +	static LLFastTimer::DeclareTimer FTM_TRANSFORM_DO_WORK("Transform Work"); +	if (use_transform_feedback) +	{ //using transform feedback, wait for transform feedback to complete +		LLFastTimer t(FTM_TRANSFORM_WAIT); + +		S32 done = 0; +		//glGetQueryivARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &count); +		 +		glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); +		 +		while (!done) +		{  +			{ +				LLFastTimer t(FTM_TRANSFORM_DO_WORK); +				F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); +				//do some useful work while we wait +				LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread +				LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread +				LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread +			} +			glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); +		} + +		mTransformFeedbackPrimitives = 0; +	}*/ +						  	//LLSpatialGroup::sNoDelete = FALSE;  	llpushcallstacks ;  } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 252fe1346c..9eebe3831f 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -161,6 +161,7 @@ public:  	void		markRebuild(LLSpatialGroup* group, BOOL priority = FALSE);  	void        markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);  	void		markPartitionMove(LLDrawable* drawablep); +	void		markMeshDirty(LLSpatialGroup* group);  	//get the object between start and end that's closest to start.  	LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end, @@ -592,6 +593,7 @@ public:  	BOOL					mVertexShadersEnabled;  	S32						mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed +	U32						mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback  protected:  	BOOL					mRenderTypeEnabled[NUM_RENDER_TYPES];  	std::stack<std::string> mRenderTypeEnableStack; @@ -649,6 +651,9 @@ protected:  	LLSpatialGroup::sg_vector_t		mGroupQ1; //priority  	LLSpatialGroup::sg_vector_t		mGroupQ2; // non-priority +	LLSpatialGroup::sg_vector_t		mMeshDirtyGroup; //groups that need rebuildMesh called +	U32 mMeshDirtyQueryObject; +  	LLDrawable::drawable_list_t		mPartitionQ; //drawables that need to update their spatial partition radius   	bool mGroupQ2Locked; | 
