diff options
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/llcubemap.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llgl.cpp | 90 | ||||
| -rw-r--r-- | indra/llrender/llgl.h | 29 | ||||
| -rw-r--r-- | indra/llrender/llglheaders.h | 13 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.cpp | 11 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.h | 4 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 123 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.h | 17 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 26 | ||||
| -rw-r--r-- | indra/llrender/llrendertarget.cpp | 47 | ||||
| -rw-r--r-- | indra/llrender/llrendertarget.h | 9 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 3 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 266 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 39 | 
15 files changed, 497 insertions, 184 deletions
| diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 45a3b18179..362452d837 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -81,7 +81,7 @@ void LLCubeMap::initGL()  		{  			U32 texname = 0; -			LLImageGL::generateTextures(1, &texname); +			LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname);  			for (int i = 0; i < 6; i++)  			{ diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 628a8d6131..0b56b3889c 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -249,6 +249,12 @@ PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL;  PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL;  PFNGLSAMPLEMASKIPROC glSampleMaski = NULL; +//transform feedback (4.0 core) +PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL; +PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL; +  //GL_ARB_debug_output  PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;  PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL; @@ -421,6 +427,7 @@ LLGLManager::LLGLManager() :  	mHasDrawBuffers(FALSE),  	mHasTextureRectangle(FALSE),  	mHasTextureMultisample(FALSE), +	mHasTransformFeedback(FALSE),  	mMaxSampleMaskWords(0),  	mMaxColorTextureSamples(0),  	mMaxDepthTextureSamples(0), @@ -558,7 +565,8 @@ bool LLGLManager::initGL()  	parse_gl_version( &mDriverVersionMajor,   		&mDriverVersionMinor,   		&mDriverVersionRelease,  -		&mDriverVersionVendorString ); +		&mDriverVersionVendorString, +		&mGLVersionString);  	mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f; @@ -938,7 +946,6 @@ void LLGLManager::initExtensions()  	mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");  	mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);  	mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); -	mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap");  	mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");  	mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");  	glh_init_extensions("GL_ARB_texture_cube_map"); @@ -963,11 +970,14 @@ void LLGLManager::initExtensions()  							ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);  #endif +	mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f; +  	mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);  	mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);  	mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);  	mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);  	mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); +	mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;  #if !LL_DARWIN  	mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);  #endif @@ -1207,7 +1217,14 @@ void LLGLManager::initExtensions()  		glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");  		glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");  		glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski"); -	}	 +	} +	if (mHasTransformFeedback) +	{ +		glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback"); +		glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback"); +		glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings"); +		glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); +	}  	if (mHasDebugOutput)  	{  		glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB"); @@ -1964,6 +1981,7 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :  			case GL_COLOR_MATERIAL:  			case GL_FOG:  			case GL_LINE_STIPPLE: +			case GL_POLYGON_STIPPLE:  				mState = 0;  				break;  		} @@ -2052,7 +2070,7 @@ void LLGLManager::initGLStates()  //////////////////////////////////////////////////////////////////////////////// -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ) +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string )  {  	// GL_VERSION returns a null-terminated string with the format:   	// <major>.<minor>[.<release>] [<vendor specific>] @@ -2068,6 +2086,8 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor  		return;  	} +	version_string->assign(version); +  	std::string ver_copy( version );  	S32 len = (S32)strlen( version );	/* Flawfinder: ignore */  	S32 i = 0; @@ -2429,3 +2449,65 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()  	gGL.matrixMode(LLRender::MM_MODELVIEW);  } + +	 +LLGLSyncFence::LLGLSyncFence() +{ +#ifdef GL_ARB_sync +	mSync = 0; +#endif +} + +LLGLSyncFence::~LLGLSyncFence() +{ +#ifdef GL_ARB_sync +	if (mSync) +	{ +		glDeleteSync(mSync); +	} +#endif +} + +void LLGLSyncFence::placeFence() +{ +#ifdef GL_ARB_sync +	if (mSync) +	{ +		glDeleteSync(mSync); +	} +	mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif +} + +bool LLGLSyncFence::isCompleted() +{ +	bool ret = true; +#ifdef GL_ARB_sync +	if (mSync) +	{ +		GLenum status = glClientWaitSync(mSync, 0, 1); +		if (status == GL_TIMEOUT_EXPIRED) +		{ +			ret = false; +		} +	} +#endif +	return ret; +} + +void LLGLSyncFence::wait() +{ +#ifdef GL_ARB_sync +	if (mSync) +	{ +		while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) +		{ //track the number of times we've waited here +			static S32 waits = 0; +			waits++; +		} +	} +#endif +} + + + diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 5a33c98708..964495a3ab 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -104,6 +104,7 @@ public:  	BOOL mHasDepthClamp;  	BOOL mHasTextureRectangle;  	BOOL mHasTextureMultisample; +	BOOL mHasTransformFeedback;  	S32 mMaxSampleMaskWords;  	S32 mMaxColorTextureSamples;  	S32 mMaxDepthTextureSamples; @@ -141,6 +142,7 @@ public:  	S32 mGLSLVersionMajor;  	S32 mGLSLVersionMinor;  	std::string mDriverVersionVendorString; +	std::string mGLVersionString;  	S32 mVRAM; // VRAM in MB  	S32 mGLMaxVertexRange; @@ -417,13 +419,38 @@ public:  	virtual void updateGL() = 0;  }; +const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000;  //1 ms + +class LLGLFence +{ +public: +	virtual void placeFence() = 0; +	virtual bool isCompleted() = 0; +	virtual void wait() = 0; +}; + +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync +	GLsync mSync; +#endif +	 +	LLGLSyncFence(); +	virtual ~LLGLSyncFence(); + +	void placeFence(); +	bool isCompleted(); +	void wait(); +}; +  extern LLMatrix4 gGLObliqueProjectionInverse;  #include "llglstates.h"  void init_glstates(); -void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific ); +void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string );  extern BOOL gClothRipple;  extern BOOL gHeadlessClient; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index d61ec707f0..a0727b8686 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -528,6 +528,13 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;  extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;  extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + +  #elif LL_WINDOWS  //----------------------------------------------------------------------------  // LL_WINDOWS @@ -759,6 +766,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;  extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;  extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//transform feedback (4.0 core) +extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback; +extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback; +extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; +  //GL_ARB_debug_output  extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;  extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 4b7e639aed..7cbf39096e 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -129,7 +129,9 @@ void LLGLSLShader::unload()  }  BOOL LLGLSLShader::createShader(vector<string> * attributes, -								vector<string> * uniforms) +								vector<string> * uniforms, +								U32 varying_count, +								const char** varyings)  {  	//reloading, reset matrix hash values  	for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) @@ -172,6 +174,13 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,  		mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);  	} +#ifdef GL_INTERLEAVED_ATTRIBS +	if (varying_count > 0 && varyings) +	{ +		glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); +	} +#endif +  	// Map attributes and uniforms  	if (success)  	{ diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7873fe3c4e..5c68cb46eb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -76,7 +76,9 @@ public:  	void unload();  	BOOL createShader(std::vector<std::string> * attributes, -						std::vector<std::string> * uniforms); +						std::vector<std::string> * uniforms, +						U32 varying_count = 0, +						const char** varyings = NULL);  	BOOL attachObject(std::string object);  	void attachObject(GLhandleARB object);  	void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c04a3f6b41..a842211764 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -42,6 +42,10 @@  //----------------------------------------------------------------------------  const F32 MIN_TEXTURE_LIFETIME = 10.f; +//which power of 2 is i? +//assumes i is a power of 2 > 0 +U32 wpo2(U32 i); +  //statics  U32 LLImageGL::sUniqueCount				= 0; @@ -50,7 +54,8 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes		= 0;  S32 LLImageGL::sBoundTextureMemoryInBytes		= 0;  S32 LLImageGL::sCurBoundTextureMemory	= 0;  S32 LLImageGL::sCount					= 0; -std::list<U32> LLImageGL::sDeadTextureList; +LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE]; +U32 LLImageGL::sCurTexName = 1;  BOOL LLImageGL::sGlobalUseAnisotropic	= FALSE;  F32 LLImageGL::sLastFrameTime			= 0.f; @@ -232,9 +237,11 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)  //---------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_STATS("Image Stats");  // static  void LLImageGL::updateStats(F32 current_time)  { +	LLFastTimer t(FTM_IMAGE_UPDATE_STATS);  	sLastFrameTime = current_time;  	sBoundTextureMemoryInBytes = sCurBoundTextureMemory;  	sCurBoundTextureMemory = 0; @@ -416,6 +423,7 @@ void LLImageGL::init(BOOL usemipmaps)  	mTarget = GL_TEXTURE_2D;  	mBindTarget = LLTexUnit::TT_TEXTURE;  	mHasMipMaps = false; +	mMipLevels = -1;  	mIsResident = 0; @@ -606,8 +614,24 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		is_compressed = true;  	} +	 +	 +	if (mUseMipMaps) +	{ +		//set has mip maps to true before binding image so tex parameters get set properly +		gGL.getTexUnit(0)->unbind(mBindTarget); +		mHasMipMaps = true; +		mTexOptionsDirty = true; +		setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +	} +	else +	{ +		mHasMipMaps = false; +	} +	  	llverify(gGL.getTexUnit(0)->bind(this)); +	  	if (mUseMipMaps)  	{  		if (data_hasmips) @@ -620,6 +644,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  				S32 w = getWidth(d);  				S32 h = getHeight(d);  				S32 gl_level = d-mCurrentDiscardLevel; + +				mMipLevels = llmax(mMipLevels, gl_level); +  				if (d > mCurrentDiscardLevel)  				{  					data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment @@ -662,10 +689,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		{  			if (mAutoGenMips)  			{ -				if (!gGLManager.mHasFramebufferObject) -				{ -					glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE); -				}  				stop_glerror();  				{  // 					LLFastTimer t2(FTM_TEMP4); @@ -679,6 +702,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  					S32 w = getWidth(mCurrentDiscardLevel);  					S32 h = getHeight(mCurrentDiscardLevel); +					mMipLevels = wpo2(llmax(w, h)); + +					//use legacy mipmap generation mode +					glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); +					  					LLImageGL::setManualImage(mTarget, 0, mFormatInternal,  								 w, h,   								 mFormatPrimary, mFormatType, @@ -694,16 +722,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  						stop_glerror();  					}  				} - -				if (gGLManager.mHasFramebufferObject) -				{ -					glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget)); -				}  			}  			else  			{  				// Create mips by hand -				// about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800  				// ~4x faster than gluBuild2DMipmaps  				S32 width = getWidth(mCurrentDiscardLevel);  				S32 height = getHeight(mCurrentDiscardLevel); @@ -713,6 +735,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  				const U8* cur_mip_data = 0;  				S32 prev_mip_size = 0;  				S32 cur_mip_size = 0; +				 +				mMipLevels = nummips; +  				for (int m=0; m<nummips; m++)  				{  					if (m==0) @@ -777,10 +802,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		{  			llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl;  		} -		mHasMipMaps = true;  	}  	else  	{ +		mMipLevels = 0;  		S32 w = getWidth();  		S32 h = getHeight();  		if (is_compressed) @@ -812,7 +837,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  			}  		} -		mHasMipMaps = false;  	}  	stop_glerror();  	mGLTextureCreated = true; @@ -1025,23 +1049,65 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_  }  // static -void LLImageGL::generateTextures(S32 numTextures, U32 *textures) +void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures)  { -	glGenTextures(numTextures, (GLuint*)textures); +	bool empty = true; + +	dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format); +	 +	if (iter != sDeadTextureList[type].end()) +	{ +		empty = iter->second.empty(); +	} +	 +	for (S32 i = 0; i < numTextures; ++i) +	{ +		if (!empty) +		{ +			textures[i] = iter->second.front(); +			iter->second.pop_front(); +			empty = iter->second.empty(); +		} +		else +		{ +			textures[i] = sCurTexName++; +		} +	}  }  // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate) +void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate)  { -	for (S32 i = 0; i < numTextures; i++) +	if (gGLManager.mInited)  	{ -		sDeadTextureList.push_back(textures[i]); -	} +		if (format == 0 ||  type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1) +		{ //unknown internal format or unknown number of mip levels, not safe to reuse +			glDeleteTextures(numTextures, textures); +		} +		else +		{ +			for (S32 i = 0; i < numTextures; ++i) +			{ //remove texture from VRAM by setting its size to zero +				for (S32 j = 0; j <= mip_levels; j++) +				{ +					gGL.getTexUnit(0)->bindManual(type, textures[i]); + +					glTexImage2D(LLTexUnit::getInternalType(type), j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); +				} + +				llassert(std::find(sDeadTextureList[type][format].begin(), +								   sDeadTextureList[type][format].end(), textures[i]) ==  +								   sDeadTextureList[type][format].end()); -	if (immediate) +				sDeadTextureList[type][format].push_back(textures[i]); +			}	 +		} +	} +	 +	/*if (immediate)  	{  		LLImageGL::deleteDeadTextures(); -	} +	}*/  }  // static @@ -1166,10 +1232,11 @@ BOOL LLImageGL::createGLTexture()  	if(mTexName)  	{ -		glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ; +		LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, (reinterpret_cast<GLuint*>(&mTexName))) ;  	} -	glGenTextures(1, (GLuint*)&mTexName); + +	LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);  	stop_glerror();  	if (!mTexName)  	{ @@ -1282,7 +1349,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_  	}  	else  	{ -		LLImageGL::generateTextures(1, &mTexName); +		LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);  		stop_glerror();  		{  			llverify(gGL.getTexUnit(0)->bind(this)); @@ -1327,7 +1394,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_  	{  		sGlobalTextureMemoryInBytes -= mTextureMemory; -		LLImageGL::deleteTextures(1, &old_name); +		LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name);  		stop_glerror();  	} @@ -1456,7 +1523,7 @@ void LLImageGL::deleteDeadTextures()  {  	bool reset = false; -	while (!sDeadTextureList.empty()) +	/*while (!sDeadTextureList.empty())  	{  		GLuint tex = sDeadTextureList.front();  		sDeadTextureList.pop_front(); @@ -1478,7 +1545,7 @@ void LLImageGL::deleteDeadTextures()  		glDeleteTextures(1, &tex);  		stop_glerror(); -	} +	}*/  	if (reset)  	{ @@ -1496,7 +1563,7 @@ void LLImageGL::destroyGLTexture()  			mTextureMemory = 0;  		} -		LLImageGL::deleteTextures(1, &mTexName);			 +		LLImageGL::deleteTextures(mBindTarget,  mFormatInternal, mMipLevels, 1, &mTexName);			  		mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.  		mTexName = 0;		  		mGLTextureCreated = FALSE ; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index f34b9fa91a..e118c28c1b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -45,8 +45,16 @@ class LLImageGL : public LLRefCount  {  	friend class LLTexUnit;  public: -	static std::list<U32> sDeadTextureList; +	static U32 sCurTexName; +	//previously used but now available texture names +	// sDeadTextureList[<usage>][<internal format>] +	typedef std::map<U32, std::list<U32> > dead_texturelist_t; +	static dead_texturelist_t sDeadTextureList[LLTexUnit::TT_NONE]; + +	// These 2 functions replace glGenTextures() and glDeleteTextures() +	static void generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures); +	static void deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate = false);  	static void deleteDeadTextures();  	// Size calculation @@ -96,10 +104,6 @@ public:  	void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}  	void setAllowCompression(bool allow) { mAllowCompression = allow; } -	// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()  -	// for tracking purposes and will be deprecated in the future -	static void generateTextures(S32 numTextures, U32 *textures); -	static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);  	static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);  	BOOL createGLTexture() ; @@ -217,7 +221,8 @@ protected:  	LLGLenum mTarget;		// Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)  	LLTexUnit::eTextureType mBindTarget;	// Normally TT_TEXTURE, sometimes something else (ex. cube maps)  	bool mHasMipMaps; -	 +	S32 mMipLevels; +  	LLGLboolean mIsResident;  	S8 mComponents; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 93bac4c779..348c1eb1b7 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -408,12 +408,14 @@ void LLTexUnit::unbind(eTextureType type)  	if (mIndex < 0) return; +	//always flush and activate for consistency  +	//   some code paths assume unbind always flushes and sets the active texture +	gGL.flush(); +	activate(); +  	// Disabled caching of binding state.  	if (mCurrTexType == type)  	{ -		gGL.flush(); - -		activate();  		mCurrTexture = 0;  		if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)  		{ @@ -464,11 +466,25 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio  	}   	else if (option >= TFO_BILINEAR)  	{ -		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); +		if (mHasMipMaps) +		{ +			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); +		} +		else +		{ +			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); +		}  	}  	else  	{ -		glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); +		if (mHasMipMaps) +		{ +			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); +		} +		else +		{ +			glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); +		}  	}  	if (gGLManager.mHasAnisotropic) diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 780f1dc484..cc5c232380 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -55,7 +55,6 @@ bool LLRenderTarget::sUseFBO = false;  LLRenderTarget::LLRenderTarget() :  	mResX(0),  	mResY(0), -	mTex(0),  	mFBO(0),  	mDepth(0),  	mStencil(0), @@ -70,6 +69,42 @@ LLRenderTarget::~LLRenderTarget()  	release();  } +void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt) +{  +	//for accounting, get the number of pixels added/subtracted +	S32 pix_diff = (resx*resy)-(mResX*mResY); +		 +	mResX = resx; +	mResY = resy; + +	for (U32 i = 0; i < mTex.size(); ++i) +	{ //resize color attachments +		gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); +		LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); +		sBytesAllocated += pix_diff*4; +	} + +	if (mDepth) +	{ //resize depth attachment +		if (mStencil) +		{ +			//use render buffers where stencil buffers are in play +			glBindRenderbuffer(GL_RENDERBUFFER, mDepth); +			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); +			glBindRenderbuffer(GL_RENDERBUFFER, 0); +		} +		else +		{ +			gGL.getTexUnit(0)->bindManual(mUsage, mDepth); +			U32 internal_type = LLTexUnit::getInternalType(mUsage); +			LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); +		} + +		sBytesAllocated += pix_diff*4; +	} +} +	 +  bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)  {  	stop_glerror(); @@ -135,7 +170,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)  	}  	U32 tex; -	LLImageGL::generateTextures(1, &tex); +	LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex);  	gGL.getTexUnit(0)->bindManual(mUsage, tex);  	stop_glerror(); @@ -193,6 +228,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)  	}  	mTex.push_back(tex); +	mInternalFormat.push_back(color_fmt);  	if (gDebugGL)  	{ //bind and unbind to validate target @@ -217,7 +253,7 @@ bool LLRenderTarget::allocateDepth()  	}  	else  	{ -		LLImageGL::generateTextures(1, &mDepth); +		LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth);  		gGL.getTexUnit(0)->bindManual(mUsage, mDepth);  		U32 internal_type = LLTexUnit::getInternalType(mUsage); @@ -294,7 +330,7 @@ void LLRenderTarget::release()  		}  		else  		{ -			LLImageGL::deleteTextures(1, &mDepth, true); +			LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true);  			stop_glerror();  		}  		mDepth = 0; @@ -326,8 +362,9 @@ void LLRenderTarget::release()  	if (mTex.size() > 0)  	{  		sBytesAllocated -= mResX*mResY*4*mTex.size(); -		LLImageGL::deleteTextures(mTex.size(), &mTex[0], true); +		LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true);  		mTex.clear(); +		mInternalFormat.clear();  	}  	mResX = mResY = 0; diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 2735ab21c5..e1a51304f1 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -57,8 +57,6 @@  */ -class LLMultisampleBuffer; -  class LLRenderTarget  {  public: @@ -74,6 +72,12 @@ public:  	//multiple calls will release previously allocated resources  	bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); +	//resize existing attachments to use new resolution and color format +	// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined +	// DO NOT use for screen space buffers or for scratch space for an image that might be uploaded +	// DO use for render targets that resize often and aren't likely to ruin someone's day if they break +	void resize(U32 resx, U32 resy, U32 color_fmt); +  	//add color buffer attachment  	//limit of 4 color attachments per render target  	bool addColorAttachment(U32 color_fmt); @@ -142,6 +146,7 @@ protected:  	U32 mResX;  	U32 mResY;  	std::vector<U32> mTex; +	std::vector<U32> mInternalFormat;  	U32 mFBO;  	U32 mDepth;  	bool mStencil; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5a6e6cab3e..d3b2d9fa74 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1026,6 +1026,9 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("size");  	mReservedUniforms.push_back("falloff"); +	mReservedUniforms.push_back("box_center"); +	mReservedUniforms.push_back("box_size"); +  	mReservedUniforms.push_back("minLuminance");  	mReservedUniforms.push_back("maxExtractAlpha"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index f792faa8f0..7a16b7c20f 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -97,6 +97,8 @@ public:  		LIGHT_CENTER,  		LIGHT_SIZE,  		LIGHT_FALLOFF, +		BOX_CENTER, +		BOX_SIZE,  		GLOW_MIN_LUMINANCE,  		GLOW_MAX_EXTRACT_ALPHA, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 823c6b9dc5..0092df6587 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -38,12 +38,6 @@  #include "llglslshader.h"  #include "llmemory.h" -#if LL_DARWIN -#define LL_VBO_POOLING 1 -#else -#define LL_VBO_POOLING 0 -#endif -  //Next Highest Power Of Two  //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2  U32 nhpo2(U32 v) @@ -71,6 +65,7 @@ U32 wpo2(U32 i)  const U32 LL_VBO_BLOCK_SIZE = 2048; +const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024;  U32 vbo_block_size(U32 size)  { //what block size will fit size? @@ -83,6 +78,7 @@ U32 vbo_block_index(U32 size)  	return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;  } +const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);  //============================================================================ @@ -95,6 +91,11 @@ LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_  U32 LLVBOPool::sBytesPooled = 0;  U32 LLVBOPool::sIndexBytesPooled = 0; +U32 LLVBOPool::sCurGLName = 1; + +std::list<U32> LLVertexBuffer::sAvailableVAOName; +U32 LLVertexBuffer::sCurVAOName = 1; +  U32 LLVertexBuffer::sAllocatedIndexBytes = 0;  U32 LLVertexBuffer::sIndexCount = 0; @@ -119,69 +120,55 @@ bool LLVertexBuffer::sUseStreamDraw = true;  bool LLVertexBuffer::sUseVAO = false;  bool LLVertexBuffer::sPreferStreamDraw = false; -const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000;  //1 ms -class LLGLSyncFence : public LLGLFence +U32 LLVBOPool::genBuffer()  { -public: -#ifdef GL_ARB_sync -	GLsync mSync; -#endif -	 -	LLGLSyncFence() -	{ -#ifdef GL_ARB_sync -		mSync = 0; -#endif -	} +	U32 ret = 0; -	virtual ~LLGLSyncFence() +	if (mGLNamePool.empty())  	{ -#ifdef GL_ARB_sync -		if (mSync) -		{ -			glDeleteSync(mSync); -		} -#endif +		ret = sCurGLName++;  	} - -	void placeFence() +	else  	{ -#ifdef GL_ARB_sync -		if (mSync) -		{ -			glDeleteSync(mSync); -		} -		mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -#endif +		ret = mGLNamePool.front(); +		mGLNamePool.pop_front();  	} -	void wait() +	return ret; +} + +void LLVBOPool::deleteBuffer(U32 name) +{ +	if (gGLManager.mInited)  	{ -#ifdef GL_ARB_sync -		if (mSync) -		{ -			while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) -			{ //track the number of times we've waited here -				static S32 waits = 0; -				waits++; -			} -		} -#endif -	} +		LLVertexBuffer::unbind(); +		glBindBufferARB(mType, name); +		glBufferDataARB(mType, 0, NULL, mUsage); -}; +		llassert(std::find(mGLNamePool.begin(), mGLNamePool.end(), name) == mGLNamePool.end()); + +		mGLNamePool.push_back(name); + +		glBindBufferARB(mType, 0); +	} +} -volatile U8* LLVBOPool::allocate(U32& name, U32 size) +LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) +: mUsage(vboUsage), mType(vboType) +{ +	mMissCount.resize(LL_VBO_POOL_SEED_COUNT); +	std::fill(mMissCount.begin(), mMissCount.end(), 0); +} + +volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)  {  	llassert(vbo_block_size(size) == size);  	volatile U8* ret = NULL; -#if LL_VBO_POOLING -  	U32 i = vbo_block_index(size);  	if (mFreeList.size() <= i) @@ -189,12 +176,18 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)  		mFreeList.resize(i+1);  	} -	if (mFreeList[i].empty()) +	if (mFreeList[i].empty() || for_seed)  	{  		//make a new buffer -		glGenBuffersARB(1, &name); +		name = genBuffer(); +		  		glBindBufferARB(mType, name); +		if (!for_seed && i < LL_VBO_POOL_SEED_COUNT) +		{ //record this miss +			mMissCount[i]++;	 +		} +  		if (mType == GL_ARRAY_BUFFER_ARB)  		{  			LLVertexBuffer::sAllocatedBytes += size; @@ -215,6 +208,25 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)  		}  		glBindBufferARB(mType, 0); + +		if (for_seed) +		{ //put into pool for future use +			llassert(mFreeList.size() > i); + +			Record rec; +			rec.mGLName = name; +			rec.mClientData = ret; +	 +			if (mType == GL_ARRAY_BUFFER_ARB) +			{ +				sBytesPooled += size; +			} +			else +			{ +				sIndexBytesPooled += size; +			} +			mFreeList[i].push_back(rec); +		}  	}  	else  	{ @@ -232,33 +244,6 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)  		mFreeList[i].pop_front();  	} -#else //no pooling - -	glGenBuffersARB(1, &name); -	glBindBufferARB(mType, name); - -	if (mType == GL_ARRAY_BUFFER_ARB) -	{ -		LLVertexBuffer::sAllocatedBytes += size; -	} -	else -	{ -		LLVertexBuffer::sAllocatedIndexBytes += size; -	} - -	if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) -	{ -		glBufferDataARB(mType, size, 0, mUsage); -		ret = (U8*) ll_aligned_malloc_16(size); -	} -	else -	{ //always use a true hint of static draw when allocating non-client-backed buffers -		glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); -	} - -	glBindBufferARB(mType, 0); - -#endif  	return ret;  } @@ -267,50 +252,47 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)  {  	llassert(vbo_block_size(size) == size); -#if LL_VBO_POOLING - -	U32 i = vbo_block_index(size); - -	llassert(mFreeList.size() > i); +	deleteBuffer(name); +	ll_aligned_free_16((U8*) buffer); -	Record rec; -	rec.mGLName = name; -	rec.mClientData = buffer; -	 -	if (buffer == NULL) +	if (mType == GL_ARRAY_BUFFER_ARB)  	{ -		glDeleteBuffersARB(1, &rec.mGLName); +		LLVertexBuffer::sAllocatedBytes -= size;  	}  	else  	{ -		if (mType == GL_ARRAY_BUFFER_ARB) -		{ -			sBytesPooled += size; -		} -		else -		{ -			sIndexBytesPooled += size; -		} -		mFreeList[i].push_back(rec); +		LLVertexBuffer::sAllocatedIndexBytes -= size;  	} -#else //no pooling -	glDeleteBuffersARB(1, &name); -	ll_aligned_free_16((U8*) buffer); +} -	if (mType == GL_ARRAY_BUFFER_ARB) +void LLVBOPool::seedPool() +{ +	U32 dummy_name = 0; + +	if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)  	{ -		LLVertexBuffer::sAllocatedBytes -= size; +		mFreeList.resize(LL_VBO_POOL_SEED_COUNT);  	} -	else + +	for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)  	{ -		LLVertexBuffer::sAllocatedIndexBytes -= size; +		if (mMissCount[i] > mFreeList[i].size()) +		{  +			U32 size = i*LL_VBO_BLOCK_SIZE; +		 +			S32 count = mMissCount[i] - mFreeList[i].size(); +			for (U32 j = 0; j < count; ++j) +			{ +				allocate(dummy_name, size, true); +			} +		}  	} -#endif  } +  void LLVBOPool::cleanup()  { -	U32 size = 1; +	U32 size = LL_VBO_BLOCK_SIZE;  	for (U32 i = 0; i < mFreeList.size(); ++i)  	{ @@ -320,8 +302,8 @@ void LLVBOPool::cleanup()  		{  			Record& r = l.front(); -			glDeleteBuffersARB(1, &r.mGLName); - +			deleteBuffer(r.mGLName); +			  			if (r.mClientData)  			{  				ll_aligned_free_16((void*) r.mClientData); @@ -341,8 +323,11 @@ void LLVBOPool::cleanup()  			}  		} -		size *= 2; +		size += LL_VBO_BLOCK_SIZE;  	} + +	//reset miss counts +	std::fill(mMissCount.begin(), mMissCount.end(), 0);  } @@ -376,6 +361,41 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =  	GL_LINE_LOOP,  }; +//static +U32 LLVertexBuffer::getVAOName() +{ +	U32 ret = 0; + +	if (!sAvailableVAOName.empty()) +	{ +		ret = sAvailableVAOName.front(); +		sAvailableVAOName.pop_front(); +	} +	else +	{ +#ifdef GL_ARB_vertex_array_object +		glGenVertexArrays(1, &ret); +#endif +	} + +	return ret;		 +} + +//static +void LLVertexBuffer::releaseVAOName(U32 name) +{ +	sAvailableVAOName.push_back(name); +} + + +//static +void LLVertexBuffer::seedPools() +{ +	sStreamVBOPool.seedPool(); +	sDynamicVBOPool.seedPool(); +	sStreamIBOPool.seedPool(); +	sDynamicIBOPool.seedPool(); +}  //static  void LLVertexBuffer::setupClientArrays(U32 data_mask) @@ -985,7 +1005,7 @@ LLVertexBuffer::~LLVertexBuffer()  	if (mGLArray)  	{  #if GL_ARB_vertex_array_object -		glDeleteVertexArrays(1, &mGLArray); +		releaseVAOName(mGLArray);  #endif  	} @@ -1211,10 +1231,10 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)  	llassert(nverts >= 0); -	if (nverts >= 65535) +	if (nverts > 65536)  	{  		llwarns << "Vertex buffer overflow!" << llendl; -		nverts = 65535; +		nverts = 65536;  	}  	U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts); @@ -1270,7 +1290,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)  		if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO))  		{  #if GL_ARB_vertex_array_object -			glGenVertexArrays(1, &mGLArray); +			mGLArray = getVAOName();  #endif  			setupVertexArray();  		} @@ -2140,6 +2160,16 @@ void LLVertexBuffer::flush()  	}  } +// bind for transform feedback (quick 'n dirty) +void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count) +{ +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER +	U32 offset = mOffsets[type] + sTypeSize[type]*index; +	U32 size= (sTypeSize[type]*count); +	glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size); +#endif +} +  // Set for rendering  void LLVertexBuffer::setBuffer(U32 data_mask)  { @@ -2291,10 +2321,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  	stop_glerror();  	volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; -	/*if ((data_mask & mTypeMask) != data_mask) +	if (gDebugGL && ((data_mask & mTypeMask) != data_mask))  	{  		llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; -	}*/ +	}  	if (LLGLSLShader::sNoFixedFunction)  	{ diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 7477dec3ad..11fa4ab6a0 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -57,23 +57,28 @@ public:  	static U32 sBytesPooled;  	static U32 sIndexBytesPooled; -	LLVBOPool(U32 vboUsage, U32 vboType) -		: mUsage(vboUsage) -		, mType(vboType) -	{} +	static U32 sCurGLName; +	LLVBOPool(U32 vboUsage, U32 vboType); +		  	const U32 mUsage;  	const U32 mType;  	//size MUST be a power of 2 -	volatile U8* allocate(U32& name, U32 size); +	volatile U8* allocate(U32& name, U32 size, bool for_seed = false);  	//size MUST be the size provided to allocate that returned the given name  	void release(U32 name, volatile U8* buffer, U32 size); +	//batch allocate buffers to be provided to the application on demand +	void seedPool(); +  	//destroy all records in mFreeList  	void cleanup(); +	U32 genBuffer(); +	void deleteBuffer(U32 name); +  	class Record  	{  	public: @@ -81,17 +86,15 @@ public:  		volatile U8* mClientData;  	}; +	std::list<U32> mGLNamePool; +  	typedef std::list<Record> record_list_t;  	std::vector<record_list_t> mFreeList; -}; +	std::vector<U32> mMissCount; -class LLGLFence -{ -public: -	virtual void placeFence() = 0; -	virtual void wait() = 0;  }; +  //============================================================================  // base class   class LLPrivateMemoryPool; @@ -125,13 +128,22 @@ public:  	static LLVBOPool sStreamIBOPool;  	static LLVBOPool sDynamicIBOPool; +	static std::list<U32> sAvailableVAOName; +	static U32 sCurVAOName; +  	static bool	sUseStreamDraw;  	static bool sUseVAO;  	static bool	sPreferStreamDraw; +	static void seedPools(); + +	static U32 getVAOName(); +	static void releaseVAOName(U32 name); +  	static void initClass(bool use_vbo, bool no_vbo_mapping);  	static void cleanupClass();  	static void setupClientArrays(U32 data_mask); +	static void pushPositions(U32 mode, const LLVector4a* pos, U32 count);  	static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);  	static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); @@ -208,7 +220,6 @@ protected:  	void 	destroyGLIndices();  	void	updateNumVerts(S32 nverts);  	void	updateNumIndices(S32 nindices);  -	bool	useVBOs() const;  	void	unmapBuffer();  public: @@ -218,6 +229,8 @@ public:  	volatile U8*		mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);  	volatile U8*		mapIndexBuffer(S32 index, S32 count, bool map_range); +	void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); +  	// set for rendering  	virtual void	setBuffer(U32 data_mask); 	// calls  setupVertexBuffer() if data_mask is not 0  	void flush(); //flush pending data to GL memory @@ -240,12 +253,14 @@ public:  	bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); +	bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);  	bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); +	bool useVBOs() const;  	bool isEmpty() const					{ return mEmpty; }  	bool isLocked() const					{ return mVertexLocked || mIndexLocked; }  	S32 getNumVerts() const					{ return mNumVerts; } | 
