diff options
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llrender/llgl.cpp | 26 | ||||
| -rw-r--r-- | indra/llrender/llgl.h | 8 | ||||
| -rw-r--r-- | indra/llrender/llgldbg.cpp | 223 | ||||
| -rw-r--r-- | indra/llrender/llgldbg.h | 34 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.cpp | 164 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.h | 57 | ||||
| -rw-r--r-- | indra/llrender/llglstates.h | 65 | ||||
| -rw-r--r-- | indra/llrender/llrender2dutils.cpp | 5 | ||||
| -rw-r--r-- | indra/llrender/llrender2dutils.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 298 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.h | 21 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 10 | 
13 files changed, 383 insertions, 532 deletions
| diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 92ebdb9490..9454943dc5 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -18,7 +18,6 @@ set(llrender_SOURCE_FILES      llfontgl.cpp      llfontregistry.cpp      llgl.cpp -    llgldbg.cpp      llglslshader.cpp      llgltexture.cpp      llimagegl.cpp @@ -46,7 +45,6 @@ set(llrender_HEADER_FILES      llfontbitmapcache.h      llfontregistry.h      llgl.h -    llgldbg.h      llglheaders.h      llglslshader.h      llglstates.h diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 303edddfaf..ae408dae4f 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2454,32 +2454,11 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :  	mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; -	switch (state) -	{ -		case GL_ALPHA_TEST: -		case GL_NORMALIZE: -		case GL_TEXTURE_GEN_R: -		case GL_TEXTURE_GEN_S: -		case GL_TEXTURE_GEN_T: -		case GL_TEXTURE_GEN_Q: -		case GL_LIGHTING: -		case GL_COLOR_MATERIAL: -		case GL_FOG: -		case GL_LINE_STIPPLE: -		case GL_POLYGON_STIPPLE: -			mState = 0; -			break; -	} - -	stop_glerror();  	if (mState)  	{  		mWasEnabled = sStateMap[state]; -        // we can't actually assert on this as queued changes to state are not reflected by glIsEnabled -		//llassert(mWasEnabled == glIsEnabled(state));  		setEnabled(enabled); -		stop_glerror();  	}  } @@ -2511,7 +2490,6 @@ void LLGLState::setEnabled(S32 enabled)  LLGLState::~LLGLState()   {      LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; -	stop_glerror();  	if (mState)  	{  		if (gDebugGL) @@ -2544,7 +2522,6 @@ LLGLState::~LLGLState()  			}  		}  	} -	stop_glerror();  }  //////////////////////////////////////////////////////////////////////////////// @@ -2921,8 +2898,7 @@ void LLGLSyncFence::wait()  }  LLGLSPipelineSkyBox::LLGLSPipelineSkyBox() -: mAlphaTest(GL_ALPHA_TEST) -, mCullFace(GL_CULL_FACE) +: mCullFace(GL_CULL_FACE)  , mSquashClip()  {   } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index eb0650d998..4b0fbc0466 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -192,13 +192,13 @@ void clear_glerror();  	//disable lighting for rendering hud objects  	//INCORRECT USAGE -	LLGLEnable lighting(GL_LIGHTING); +	LLGLEnable blend(GL_BLEND);  	renderHUD(); -	LLGLDisable lighting(GL_LIGHTING); +	LLGLDisable blend(GL_BLEND);  	//CORRECT USAGE  	{ -		LLGLEnable lighting(GL_LIGHTING); +		LLGLEnable blend(GL_BLEND);  		renderHUD();  	} @@ -206,7 +206,7 @@ void clear_glerror();  	is useful:  	{ -		LLGLEnable lighting(light_hud ? GL_LIGHTING : 0); +		LLGLEnable blend(blend_hud ? GL_GL_BLEND: 0);  		renderHUD();  	} diff --git a/indra/llrender/llgldbg.cpp b/indra/llrender/llgldbg.cpp deleted file mode 100644 index 0f1d4ae742..0000000000 --- a/indra/llrender/llgldbg.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/**  - * @file llgldbg.cpp - * @brief Definitions for OpenGL debugging support - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -// This file sets some global GL parameters, and implements some  -// useful functions for GL operations. - -#include "linden_common.h" - -#include "llgldbg.h" - -#include "llgl.h" -#include "llglheaders.h" - - -//------------------------------------------------------------------------ -// cmstr() -//------------------------------------------------------------------------ -const char *cmstr(int i) -{ -	switch( i ) -	{ -	case GL_EMISSION: return "GL_EMISSION"; -	case GL_AMBIENT: return "GL_AMBIENT"; -	case GL_DIFFUSE: return "GL_DIFFUSE"; -	case GL_SPECULAR: return "GL_SPECULAR"; -	case GL_AMBIENT_AND_DIFFUSE: return "GL_AMBIENT_AND_DIFFUSE"; -	} -	return "UNKNOWN"; -} - -//------------------------------------------------------------------------ -// facestr() -//------------------------------------------------------------------------ -const char *facestr(int i) -{ -	switch( i ) -	{ -	case GL_FRONT: return "GL_FRONT"; -	case GL_BACK: return "GL_BACK"; -	case GL_FRONT_AND_BACK: return "GL_FRONT_AND_BACK"; -	} -	return "UNKNOWN"; -} - -//------------------------------------------------------------------------ -// boolstr() -//------------------------------------------------------------------------ -const char *boolstr(int b) -{ -	return b ? "GL_TRUE" : "GL_FALSE"; -} - -//------------------------------------------------------------------------ -// fv4() -//------------------------------------------------------------------------ -const char *fv4(F32 *f) -{ -	static char str[128]; -	sprintf(str, "%8.3f %8.3f %8.3f %8.3f", f[0], f[1], f[2], f[3]); -	return str; -} - -//------------------------------------------------------------------------ -// fv3() -//------------------------------------------------------------------------ -const char *fv3(F32 *f) -{ -	static char str[128];	/* Flawfinder: ignore */ -	snprintf(str, sizeof(str), "%8.3f, %8.3f, %8.3f", f[0], f[1], f[2]);	/* Flawfinder: ignore */ -	return str; -} - -//------------------------------------------------------------------------ -// fv1() -//------------------------------------------------------------------------ -const char *fv1(F32 *f) -{ -	static char str[128];	/* Flawfinder: ignore */ -	snprintf(str, sizeof(str), "%8.3f", f[0]);		/* Flawfinder: ignore */ -	return str; -} - -//------------------------------------------------------------------------ -// llgl_dump() -//------------------------------------------------------------------------ -void llgl_dump() -{ -	int i; -	F32 fv[16]; -	GLboolean b; - -	LL_INFOS() << "==========================" << LL_ENDL; -	LL_INFOS() << "OpenGL State" << LL_ENDL; -	LL_INFOS() << "==========================" << LL_ENDL; - -	LL_INFOS() << "-----------------------------------" << LL_ENDL; -	LL_INFOS() << "Current Values" << LL_ENDL; -	LL_INFOS() << "-----------------------------------" << LL_ENDL; - -	glGetFloatv(GL_CURRENT_COLOR, fv); -	LL_INFOS() << "GL_CURRENT_COLOR          : " << fv4(fv) << LL_ENDL; - -	glGetFloatv(GL_CURRENT_NORMAL, fv); -	LL_INFOS() << "GL_CURRENT_NORMAL          : " << fv3(fv) << LL_ENDL; - -	LL_INFOS() << "-----------------------------------" << LL_ENDL; -	LL_INFOS() << "Lighting" << LL_ENDL; -	LL_INFOS() << "-----------------------------------" << LL_ENDL; - -	LL_INFOS() << "GL_LIGHTING                : " << boolstr(glIsEnabled(GL_LIGHTING)) << LL_ENDL; - -	LL_INFOS() << "GL_COLOR_MATERIAL          : " << boolstr(glIsEnabled(GL_COLOR_MATERIAL)) << LL_ENDL; - -	glGetIntegerv(GL_COLOR_MATERIAL_PARAMETER, (GLint*)&i); -	LL_INFOS() << "GL_COLOR_MATERIAL_PARAMETER: " << cmstr(i) << LL_ENDL; - -	glGetIntegerv(GL_COLOR_MATERIAL_FACE, (GLint*)&i); -	LL_INFOS() << "GL_COLOR_MATERIAL_FACE     : " << facestr(i) << LL_ENDL; - -	fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f; -	glGetMaterialfv(GL_FRONT, GL_AMBIENT, fv); -	LL_INFOS() << "GL_AMBIENT material        : " << fv4(fv) << LL_ENDL; - -	fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f; -	glGetMaterialfv(GL_FRONT, GL_DIFFUSE, fv); -	LL_INFOS() << "GL_DIFFUSE material        : " << fv4(fv) << LL_ENDL; - -	fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f; -	glGetMaterialfv(GL_FRONT, GL_SPECULAR, fv); -	LL_INFOS() << "GL_SPECULAR material       : " << fv4(fv) << LL_ENDL; - -	fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f; -	glGetMaterialfv(GL_FRONT, GL_EMISSION, fv); -	LL_INFOS() << "GL_EMISSION material       : " << fv4(fv) << LL_ENDL; - -	fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f; -	glGetMaterialfv(GL_FRONT, GL_SHININESS, fv); -	LL_INFOS() << "GL_SHININESS material      : " << fv1(fv) << LL_ENDL; - -	fv[0] = fv[1] = fv[2] = fv[3] = 12345.6789f; -	glGetFloatv(GL_LIGHT_MODEL_AMBIENT, fv); -	LL_INFOS() << "GL_LIGHT_MODEL_AMBIENT     : " << fv4(fv) << LL_ENDL; - -	glGetBooleanv(GL_LIGHT_MODEL_LOCAL_VIEWER, &b); -	LL_INFOS() << "GL_LIGHT_MODEL_LOCAL_VIEWER: " << boolstr(b) << LL_ENDL; - -	glGetBooleanv(GL_LIGHT_MODEL_TWO_SIDE, &b); -	LL_INFOS() << "GL_LIGHT_MODEL_TWO_SIDE    : " << boolstr(b) << LL_ENDL; - -	for (int l=0; l<8; l++) -	{ -	b = glIsEnabled(GL_LIGHT0+l); -	LL_INFOS() << "GL_LIGHT" << l << "                  : " << boolstr(b) << LL_ENDL; - -	if (!b) -		continue; - -	glGetLightfv(GL_LIGHT0+l, GL_AMBIENT, fv); -	LL_INFOS() << "  GL_AMBIENT light         : " << fv4(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_DIFFUSE, fv); -	LL_INFOS() << "  GL_DIFFUSE light         : " << fv4(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_SPECULAR, fv); -	LL_INFOS() << "  GL_SPECULAR light        : " << fv4(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_POSITION, fv); -	LL_INFOS() << "  GL_POSITION light        : " << fv4(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_CONSTANT_ATTENUATION, fv); -	LL_INFOS() << "  GL_CONSTANT_ATTENUATION  : " << fv1(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_QUADRATIC_ATTENUATION, fv); -	LL_INFOS() << "  GL_QUADRATIC_ATTENUATION : " << fv1(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_SPOT_DIRECTION, fv); -	LL_INFOS() << "  GL_SPOT_DIRECTION        : " << fv4(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_SPOT_EXPONENT, fv); -	LL_INFOS() << "  GL_SPOT_EXPONENT         : " << fv1(fv) << LL_ENDL; - -	glGetLightfv(GL_LIGHT0+l, GL_SPOT_CUTOFF, fv); -	LL_INFOS() << "  GL_SPOT_CUTOFF           : " << fv1(fv) << LL_ENDL; -	} - -	LL_INFOS() << "-----------------------------------" << LL_ENDL; -	LL_INFOS() << "Pixel Operations" << LL_ENDL; -	LL_INFOS() << "-----------------------------------" << LL_ENDL; - -	LL_INFOS() << "GL_ALPHA_TEST              : " << boolstr(glIsEnabled(GL_ALPHA_TEST)) << LL_ENDL; -	LL_INFOS() << "GL_DEPTH_TEST              : " << boolstr(glIsEnabled(GL_DEPTH_TEST)) << LL_ENDL; - -	glGetBooleanv(GL_DEPTH_WRITEMASK, &b); -	LL_INFOS() << "GL_DEPTH_WRITEMASK         : " << boolstr(b) << LL_ENDL; -	 -	LL_INFOS() << "GL_BLEND                   : " << boolstr(glIsEnabled(GL_BLEND)) << LL_ENDL; -	LL_INFOS() << "GL_DITHER                  : " << boolstr(glIsEnabled(GL_DITHER)) << LL_ENDL; -} - -// End diff --git a/indra/llrender/llgldbg.h b/indra/llrender/llgldbg.h deleted file mode 100644 index 963579cb82..0000000000 --- a/indra/llrender/llgldbg.h +++ /dev/null @@ -1,34 +0,0 @@ -/**  - * @file llgldbg.h - * @brief Definitions for OpenGL debugging support - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLGLDBG_H -#define LL_LLGLDBG_H - -// Dumps the current OpenGL state to the console. -void llgl_dump(); - - -#endif // LL_LLGLDBG_H diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index b7f08aa9af..ccfb8f69be 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -34,6 +34,9 @@  #include "llvertexbuffer.h"  #include "llrendertarget.h" +#include "hbxxh.h" +#include "llsdserialize.h" +  #if LL_DARWIN  #include "OpenGL/OpenGL.h"  #endif @@ -53,6 +56,7 @@ LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;  S32 LLGLSLShader::sIndexedTextureChannels = 0;  bool LLGLSLShader::sProfileEnabled = false;  std::set<LLGLSLShader*> LLGLSLShader::sInstances; +LLGLSLShader::defines_map_t LLGLSLShader::sGlobalDefines;  U64 LLGLSLShader::sTotalTimeElapsed = 0;  U32 LLGLSLShader::sTotalTrianglesDrawn = 0;  U64 LLGLSLShader::sTotalSamplesDrawn = 0; @@ -82,31 +86,6 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)      return v1 != v2;  } -LLShaderFeatures::LLShaderFeatures() -    : calculatesLighting(false) -    , calculatesAtmospherics(false) -    , hasLighting(false) -    , isAlphaLighting(false) -    , isSpecular(false) -    , hasWaterFog(false) -    , hasTransport(false) -    , hasSkinning(false) -    , hasObjectSkinning(false) -    , hasAtmospherics(false) -    , hasGamma(false) -    , hasSrgb(false) -    , encodesNormal(false) -    , isDeferred(false) -    , hasScreenSpaceReflections(false) -    , hasShadows(false) -    , hasAmbientOcclusion(false) -    , mIndexedTextureChannels(0) -    , disableTextureIndex(false) -    , hasAlphaMask(false) -    , attachNothing(false) -{ -} -  //===============================  // LLGLSL Shader implementation  //=============================== @@ -329,6 +308,7 @@ LLGLSLShader::LLGLSLShader()      mActiveTextureChannels(0),      mShaderLevel(0),      mShaderGroup(SG_DEFAULT), +    mFeatures(),      mUniformsDirty(FALSE),      mTimerQuery(0),      mSamplesQuery(0), @@ -345,6 +325,7 @@ void LLGLSLShader::unload()  {      mShaderFiles.clear();      mDefines.clear(); +    mFeatures = LLShaderFeatures();      unloadInternal();  } @@ -420,6 +401,13 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes,      llassert_always(!mShaderFiles.empty()); +#if LL_DARWIN +    // work-around missing mix(vec3,vec3,bvec3) +    mDefines["OLD_SELECT"] = "1"; +#endif + +    mShaderHash = hash(); +      // Create program      mProgramObject = glCreateProgram();      if (mProgramObject == 0) @@ -432,50 +420,37 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes,      BOOL success = TRUE; -#if LL_DARWIN -    // work-around missing mix(vec3,vec3,bvec3) -    mDefines["OLD_SELECT"] = "1"; -#endif +    mUsingBinaryProgram =  LLShaderMgr::instance()->loadCachedProgramBinary(this); +	if (!mUsingBinaryProgram) +	{  #if DEBUG_SHADER_INCLUDES -    fprintf(stderr, "--- %s ---\n", mName.c_str()); +	    fprintf(stderr, "--- %s ---\n", mName.c_str());  #endif // DEBUG_SHADER_INCLUDES -    //compile new source -    vector< pair<string, GLenum> >::iterator fileIter = mShaderFiles.begin(); -    for (; fileIter != mShaderFiles.end(); fileIter++) -    { -        GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); -        LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; -        if (shaderhandle) -        { -            attachObject(shaderhandle); -        } -        else -        { -            success = FALSE; -        } +        //compile new source +		vector< pair<string, GLenum> >::iterator fileIter = mShaderFiles.begin(); +		for (; fileIter != mShaderFiles.end(); fileIter++) +		{ +			GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); +			LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; +			if (shaderhandle) +			{ +				attachObject(shaderhandle); +			} +			else +			{ +				success = FALSE; +			} +		}      }      // Attach existing objects      if (!LLShaderMgr::instance()->attachShaderFeatures(this))      { +        unloadInternal();          return FALSE;      } - -    if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 3) -    { //indexed texture rendering requires GLSL 1.3 or later -        //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again -        mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); -    } - -#ifdef GL_INTERLEAVED_ATTRIBS -    if (varying_count > 0 && varyings) -    { -        glTransformFeedbackVaryings((GLuint64)mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); -    } -#endif -      // Map attributes and uniforms      if (success)      { @@ -496,6 +471,11 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes,              mShaderLevel--;              return createShader(attributes, uniforms);          } +        else +        { +            // Give up and unload shader. +            unloadInternal(); +        }      }      else if (mFeatures.mIndexedTextureChannels > 0)      { //override texture channels for indexed texture rendering @@ -570,6 +550,9 @@ BOOL LLGLSLShader::attachVertexObject(std::string object_path)  BOOL LLGLSLShader::attachFragmentObject(std::string object_path)  { +    if(mUsingBinaryProgram) +        return TRUE; +      if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0)      {          stop_glerror(); @@ -589,6 +572,9 @@ BOOL LLGLSLShader::attachFragmentObject(std::string object_path)  void LLGLSLShader::attachObject(GLuint object)  { +    if(mUsingBinaryProgram) +        return; +      if (object != 0)      {          stop_glerror(); @@ -607,6 +593,9 @@ void LLGLSLShader::attachObject(GLuint object)  void LLGLSLShader::attachObjects(GLuint* objects, S32 count)  { +    if(mUsingBinaryProgram) +        return; +      for (S32 i = 0; i < count; i++)      {          attachObject(objects[i]); @@ -617,15 +606,19 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attrib  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; -    //before linking, make sure reserved attributes always have consistent locations -    for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) -    { -        const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); -        glBindAttribLocation(mProgramObject, i, (const GLchar*)name); -    } +	BOOL res = TRUE; +	if (!mUsingBinaryProgram) +	{ +		//before linking, make sure reserved attributes always have consistent locations +		for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) +		{ +			const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); +			glBindAttribLocation(mProgramObject, i, (const GLchar*)name); +		} -    //link the program -    BOOL res = link(); +		//link the program +		res = link(); +	}      mAttribute.clear();      U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); @@ -747,7 +740,6 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString>* u          }          LLStaticHashedString hashedName(name); -        mUniformNameMap[location] = name;          mUniformMap[hashedName] = location;          LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL; @@ -799,7 +791,7 @@ void LLGLSLShader::addConstant(const LLGLSLShader::eShaderConsts shader_const)  void LLGLSLShader::removePermutation(std::string name)  { -    mDefines[name].erase(); +    mDefines.erase(name);  }  GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size) @@ -848,7 +840,6 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString>* uniforms)      mActiveTextureChannels = 0;      mUniform.clear();      mUniformMap.clear(); -    mUniformNameMap.clear();      mTexture.clear();      mValue.clear();      //initialize arrays @@ -1021,6 +1012,11 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)          LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName);      } +    if (success) +    { +        LLShaderMgr::instance()->saveCachedProgramBinary(this); +    } +      return success;  } @@ -1919,6 +1915,36 @@ void LLShaderUniforms::apply(LLGLSLShader* shader)      }  } +LLUUID LLGLSLShader::hash() +{ +    HBXXH128 hash_obj; +    hash_obj.update(mName); +    hash_obj.update(&mShaderGroup, sizeof(mShaderGroup)); +    hash_obj.update(&mShaderLevel, sizeof(mShaderLevel)); +    for (const auto& shdr_pair : mShaderFiles) +    { +        hash_obj.update(shdr_pair.first); +        hash_obj.update(&shdr_pair.second, sizeof(GLenum)); +    } +    for (const auto& define_pair : mDefines) +    { +        hash_obj.update(define_pair.first); +        hash_obj.update(define_pair.second); + +    } +    for (const auto& define_pair : LLGLSLShader::sGlobalDefines) +    { +        hash_obj.update(define_pair.first); +        hash_obj.update(define_pair.second); + +    } +    hash_obj.update(&mFeatures, sizeof(LLShaderFeatures)); +    hash_obj.update(gGLManager.mGLVendor); +    hash_obj.update(gGLManager.mGLRenderer); +    hash_obj.update(gGLManager.mGLVersionString); +    return hash_obj.digest(); +} +  #ifdef LL_PROFILER_ENABLE_RENDER_DOC  void LLGLSLShader::setLabel(const char* label) {      LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 3e7dae6669..b8071248e2 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -35,32 +35,28 @@  class LLShaderFeatures  {  public: -    bool calculatesLighting; -    bool calculatesAtmospherics; -    bool hasLighting; // implies no transport (it's possible to have neither though) -    bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions) -    bool isSpecular; -    bool hasWaterFog; // implies no gamma -    bool hasTransport; // implies no lighting (it's possible to have neither though) -    bool hasSkinning; -    bool hasObjectSkinning; -    bool hasAtmospherics; -    bool hasGamma; -    bool hasShadows; -    bool hasAmbientOcclusion; -    bool hasSrgb; -    bool encodesNormal; // include: shaders\class1\environment\encodeNormF.glsl -    bool isDeferred; -    bool hasScreenSpaceReflections; -    S32 mIndexedTextureChannels; -    bool disableTextureIndex; -    bool hasAlphaMask; +    S32 mIndexedTextureChannels = 0; +    bool calculatesLighting = false; +    bool calculatesAtmospherics = false; +    bool hasLighting = false; // implies no transport (it's possible to have neither though) +    bool isAlphaLighting = false; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions) +    bool isSpecular = false; +    bool hasWaterFog = false; // implies no gamma +    bool hasTransport = false; // implies no lighting (it's possible to have neither though) +    bool hasSkinning = false; +    bool hasObjectSkinning = false; +    bool hasAtmospherics = false; +    bool hasGamma = false; +    bool hasShadows = false; +    bool hasAmbientOcclusion = false; +    bool hasSrgb = false; +    bool encodesNormal = false; // include: shaders\class1\environment\encodeNormF.glsl +    bool isDeferred = false; +    bool hasScreenSpaceReflections = false; +    bool disableTextureIndex = false; +    bool hasAlphaMask = false;      bool hasReflectionProbes = false; -    bool attachNothing; - -    // char numLights; - -    LLShaderFeatures(); +    bool attachNothing = false;  };  // ============= Structure for caching shader uniforms =============== @@ -261,6 +257,10 @@ public:      //helper to conditionally bind mRiggedVariant instead of this      void bind(bool rigged); +    bool isComplete() const { return mProgramObject != 0; } + +    LLUUID hash(); +      // Unbinds any previously bound shader by explicitly binding no shader.      static void unbind(); @@ -283,9 +283,7 @@ public:      U32 mAttributeMask;  //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())      std::vector<GLint> mUniform;   //lookup table of uniform enum to uniform location      LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location -    typedef std::unordered_map<GLint, std::string> uniform_name_map_t;      typedef std::unordered_map<GLint, LLVector4> uniform_value_map_t; -    uniform_name_map_t mUniformNameMap; //lookup map of uniform location to uniform name      uniform_value_map_t mValue; //lookup map of uniform location to last known value      std::vector<GLint> mTexture;      S32 mTotalUniformSize; @@ -296,8 +294,11 @@ public:      LLShaderFeatures mFeatures;      std::vector< std::pair< std::string, GLenum > > mShaderFiles;      std::string mName; -    typedef std::unordered_map<std::string, std::string> defines_map_t; +    typedef std::map<std::string, std::string> defines_map_t; //NOTE: this must be an ordered map to maintain hash consistency      defines_map_t mDefines; +    static defines_map_t sGlobalDefines; +    LLUUID mShaderHash; +    bool mUsingBinaryProgram = false;      //statistics for profiling shader performance      bool mProfilePending = false; diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index c46585eab4..930c5e3ed7 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -56,77 +56,44 @@ private:  class LLGLSDefault  {  protected: -	LLGLEnable mColorMaterial; -	LLGLDisable mAlphaTest, mBlend, mCullFace, mDither,  -		mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth, -		mGLMultisample; +    LLGLDisable mBlend, mCullFace;  public:  	LLGLSDefault()  		: -		// Enable -		mColorMaterial(GL_COLOR_MATERIAL),  		// Disable -		mAlphaTest(GL_ALPHA_TEST),  		mBlend(GL_BLEND),  -		mCullFace(GL_CULL_FACE), -		mDither(GL_DITHER), -		mLineSmooth(GL_LINE_SMOOTH), -		mLineStipple(GL_LINE_STIPPLE), -		mNormalize(GL_NORMALIZE), -		mPolygonSmooth(GL_POLYGON_SMOOTH), -		mGLMultisample(GL_MULTISAMPLE) +		mCullFace(GL_CULL_FACE)  	{ }  };  class LLGLSObjectSelect  {   protected: -	LLGLDisable mBlend, mAlphaTest; +	LLGLDisable mBlend;  	LLGLEnable mCullFace;  public:  	LLGLSObjectSelect()  		: mBlend(GL_BLEND),  -		  mAlphaTest(GL_ALPHA_TEST),  		  mCullFace(GL_CULL_FACE)  	{ }  }; -class LLGLSObjectSelectAlpha -{ -protected: -	LLGLEnable mAlphaTest; -public: -	LLGLSObjectSelectAlpha() -		: mAlphaTest(GL_ALPHA_TEST) -	{} -}; -  //----------------------------------------------------------------------------  class LLGLSUIDefault  {   protected: -	LLGLEnable mBlend, mAlphaTest; +	LLGLEnable mBlend;  	LLGLDisable mCullFace;  	LLGLDepthTest mDepthTest;  public:  	LLGLSUIDefault()  -		: mBlend(GL_BLEND), mAlphaTest(GL_ALPHA_TEST), +		: mBlend(GL_BLEND),  		  mCullFace(GL_CULL_FACE),  		  mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL)  	{}  }; -class LLGLSNoAlphaTest // : public LLGLSUIDefault -{ -protected: -	LLGLDisable mAlphaTest; -public: -	LLGLSNoAlphaTest() -		: mAlphaTest(GL_ALPHA_TEST) -	{} -}; -  //----------------------------------------------------------------------------  class LLGLSPipeline @@ -144,11 +111,10 @@ public:  class LLGLSPipelineAlpha // : public LLGLSPipeline  {   protected: -	LLGLEnable mBlend, mAlphaTest; +	LLGLEnable mBlend;  public:  	LLGLSPipelineAlpha() -		: mBlend(GL_BLEND), -		  mAlphaTest(GL_ALPHA_TEST) +		: mBlend(GL_BLEND)  	{ }  }; @@ -162,20 +128,9 @@ public:  	{}  }; -class LLGLSPipelineAvatar -{ -protected: -	LLGLEnable mNormalize; -public: -	LLGLSPipelineAvatar() -		: mNormalize(GL_NORMALIZE) -	{} -}; -  class LLGLSPipelineSkyBox  {   protected: -	LLGLDisable mAlphaTest;      LLGLDisable mCullFace;      LLGLSquashToFarClip mSquashClip;  public: @@ -201,13 +156,11 @@ public:  class LLGLSTracker  {  protected: -	LLGLEnable mCullFace, mBlend, mAlphaTest; +	LLGLEnable mCullFace, mBlend;  public:  	LLGLSTracker() :  		mCullFace(GL_CULL_FACE), -		mBlend(GL_BLEND), -		mAlphaTest(GL_ALPHA_TEST) -		 +		mBlend(GL_BLEND)  	{ }  }; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 2d6f3c9469..52869406d2 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -712,11 +712,8 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre  	}  } -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) +void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color)  { -	// Stippled line -	LLGLEnable stipple(GL_LINE_STIPPLE); -	  	gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);  	gGL.flush(); diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 206e68f084..135738c3ba 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -79,7 +79,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre  void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);  void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true); -void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );  +void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color);   void gl_rect_2d_simple_tex( S32 width, S32 height ); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 614ddc0c62..01bad3a684 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -29,6 +29,9 @@  #include "llrender.h"  #include "llfile.h"  #include "lldir.h" +#include "llsdutil.h" +#include "llsdserialize.h" +#include "hbxxh.h"  #if LL_DARWIN  #include "OpenGL/OpenGL.h" @@ -276,7 +279,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		}  	} -	if (features->hasAtmospherics || features->isDeferred || features->hasTransport) +	if (features->hasAtmospherics || features->isDeferred)      {          if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) {              return FALSE; @@ -288,14 +291,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		}  	} -	if (features->hasTransport) -	{ -        if (!shader->attachFragmentObject("windlight/transportF.glsl")) -		{ -			return FALSE; -		} -	} -  	// NOTE order of shader object attaching is VERY IMPORTANT!!!  	if (features->hasWaterFog)  	{ @@ -492,7 +487,7 @@ void LLShaderMgr::dumpObjectLog(GLuint ret, BOOL warns, const std::string& filen  	}   } -GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels) +GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines, S32 texture_index_channels)  {  // endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl) @@ -596,30 +591,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  	if (major_version == 1 && minor_version < 30)  	{ -		if (minor_version < 10) -		{ -			//should NEVER get here -- if major version is 1 and minor version is less than 10,  -			// viewer should never attempt to use shaders, continuing will result in undefined behavior -			LL_ERRS() << "Unsupported GLSL Version." << LL_ENDL; -		} - -		if (minor_version <= 19) -		{ -			shader_code_text[shader_code_count++] = strdup("#version 110\n"); -			extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n"); -			extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n"); -			extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n"); -		} -		else if (minor_version <= 29) -		{ -			//set version to 1.20 -			shader_code_text[shader_code_count++] = strdup("#version 120\n"); -       		extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_120 1\n"); -			extra_code_text[extra_code_count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n"); -			extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE attribute\n"); -			extra_code_text[extra_code_count++] = strdup("#define VARYING varying\n"); -			extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT varying\n"); -		} +        llassert(false); // GL 3.1 or later required  	}  	else  	{   @@ -656,40 +628,14 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev          }  		else  		{ -			//set version to 1.30 -			shader_code_text[shader_code_count++] = strdup("#version 130\n"); +			//set version to 1.40 +			shader_code_text[shader_code_count++] = strdup("#version 140\n");  			//some implementations of GLSL 1.30 require integer precision be explicitly declared  			extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");  			extra_code_text[extra_code_count++] = strdup("precision highp float;\n");  		} -		extra_code_text[extra_code_count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n");  		extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); - -		extra_code_text[extra_code_count++] = strdup("#define ATTRIBUTE in\n"); - -		if (type == GL_VERTEX_SHADER) -		{ //"varying" state is "out" in a vertex program, "in" in a fragment program  -			// ("varying" is deprecated after version 1.20) -			extra_code_text[extra_code_count++] = strdup("#define VARYING out\n"); -			extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat out\n"); -		} -		else -		{ -			extra_code_text[extra_code_count++] = strdup("#define VARYING in\n"); -			extra_code_text[extra_code_count++] = strdup("#define VARYING_FLAT flat in\n"); -		} - -		//backwards compatibility with legacy texture lookup syntax -		extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n"); -		extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n"); -		extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n"); -		 -		if (major_version > 1 || minor_version >= 40) -		{ //GLSL 1.40 replaces texture2DRect et al with texture -			extra_code_text[extra_code_count++] = strdup("#define texture2DRect texture\n"); -			extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n"); -		}  	}      // Use alpha float to store bit flags @@ -701,7 +647,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  	if (defines)  	{ -		for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter) +		for (auto iter = defines->begin(); iter != defines->end(); ++iter)  		{  			std::string define = "#define " + iter->first + " " + iter->second + "\n";  			extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str()); @@ -727,21 +673,21 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  		.  		uniform sampler2D texN; -		VARYING_FLAT ivec4 vary_texture_index; +		flat in int vary_texture_index;  		vec4 ret = vec4(1,0,1,1);  		vec4 diffuseLookup(vec2 texcoord)  		{ -			switch (vary_texture_index.r)) +			switch (vary_texture_index)  			{ -				case 0: ret = texture2D(tex0, texcoord); break; -				case 1: ret = texture2D(tex1, texcoord); break; -				case 2: ret = texture2D(tex2, texcoord); break; +				case 0: ret = texture(tex0, texcoord); break; +				case 1: ret = texture(tex1, texcoord); break; +				case 2: ret = texture(tex2, texcoord); break;  				.  				.  				. -				case N: return texture2D(texN, texcoord); break; +				case N: return texture(texN, texcoord); break;  			}  			return ret; @@ -759,7 +705,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  		if (texture_index_channels > 1)  		{ -			extra_code_text[extra_code_count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); +			extra_code_text[extra_code_count++] = strdup("flat in int vary_texture_index;\n");  		}  		extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); @@ -768,7 +714,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  		if (texture_index_channels == 1)  		{ //don't use flow control, that's silly -			extra_code_text[extra_code_count++] = strdup("return texture2D(tex0, texcoord);\n"); +			extra_code_text[extra_code_count++] = strdup("return texture(tex0, texcoord);\n");  			extra_code_text[extra_code_count++] = strdup("}\n");  		}  		else if (major_version > 1 || minor_version >= 30) @@ -777,7 +723,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  			{ //switches are unreliable on some NVIDIA drivers  				for (U32 i = 0; i < texture_index_channels; ++i)  				{ -					std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);  +					std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);   					extra_code_text[extra_code_count++] = strdup(if_string.c_str());  				}  				extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n"); @@ -792,7 +738,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  				//switch body  				for (S32 i = 0; i < texture_index_channels; ++i)  				{ -					std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); +					std::string case_str = llformat("\t\tcase %d: return texture(tex%d, texcoord);\n", i, i);  					extra_code_text[extra_code_count++] = strdup(case_str.c_str());  				} @@ -917,24 +863,39 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  	if (error != GL_NO_ERROR)  	{  		LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL; +		if (ret) +		{ +			glDeleteShader(ret); //no longer need handle +			ret = 0; +		}  	}  	//load source -	glShaderSource(ret, shader_code_count, (const GLchar**) shader_code_text, NULL); - -	error = glGetError(); -	if (error != GL_NO_ERROR) +	if (ret)  	{ -		LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL; +		glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL); + +		error = glGetError(); +		if (error != GL_NO_ERROR) +		{ +			LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL; +			glDeleteShader(ret); //no longer need handle +			ret = 0; +		}  	}  	//compile source -	glCompileShader(ret); - -	error = glGetError(); -	if (error != GL_NO_ERROR) +	if (ret)  	{ -		LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL; +		glCompileShader(ret); + +		error = glGetError(); +		if (error != GL_NO_ERROR) +		{ +			LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL; +			glDeleteShader(ret); //no longer need handle +			ret = 0; +		}  	}  	if (error == GL_NO_ERROR) @@ -950,6 +911,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev  			LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;  			dumpObjectLog(ret, TRUE, open_file_name);  			dumpShaderSource(shader_code_count, shader_code_text); +			glDeleteShader(ret); //no longer need handle  			ret = 0;  		}  	} @@ -1041,6 +1003,176 @@ BOOL LLShaderMgr::validateProgramObject(GLuint obj)  	return success;  } +void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version) +{ +	LL_INFOS() << "Initializing shader cache" << LL_ENDL; + +	mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled; + +	if(!mShaderCacheEnabled || mShaderCacheInitialized) +		return; + +	mShaderCacheInitialized = true; + +	mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); +	LLFile::mkdir(mShaderCacheDir); + +	{ +		std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); +		if (gDirUtilp->fileExists(meta_out_path)) +		{ +			LL_INFOS() << "Loading shader cache metadata" << LL_ENDL; + +			llifstream instream(meta_out_path); +			LLSD in_data; +			LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED); +			instream.close(); + +			if (old_cache_version == current_cache_version) +			{ +				for (const auto& data_pair : llsd::inMap(in_data)) +				{ +					ProgramBinaryData binary_info = ProgramBinaryData(); +					binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger(); +					binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger(); +					binary_info.mLastUsedTime = data_pair.second["last_used"].asReal(); +					mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info); +				} +			} +			else +			{ +				LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL; +				clearShaderCache(); +			} +		} +	} +} + +void LLShaderMgr::clearShaderCache() +{ +	std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); +	LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL; +	const std::string mask = "*"; +	gDirUtilp->deleteFilesInDir(shader_cache, mask); +	mShaderBinaryCache.clear(); +} + +void LLShaderMgr::persistShaderCacheMetadata() +{ +	if(!mShaderCacheEnabled) return; + +	LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL; + +	LLSD out = LLSD::emptyMap(); + +	static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days +	const F32 current_time = LLTimer::getTotalSeconds(); +	for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();) +	{ +		const ProgramBinaryData& shader_metadata = it->second; +		if ((shader_metadata.mLastUsedTime + LRU_TIME) < current_time) +		{ +			std::string shader_path = gDirUtilp->add(mShaderCacheDir, it->first.asString() + ".shaderbin"); +			LLFile::remove(shader_path); +			it = mShaderBinaryCache.erase(it); +		} +		else +		{ +			LLSD data = LLSD::emptyMap(); +			data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat); +			data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength); +			data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime); +			out[it->first.asString()] = data; +			++it; +		} +	} + +	std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); +	llofstream outstream(meta_out_path); +	LLSDSerialize::toNotation(out, outstream); +	outstream.close(); +} + +bool LLShaderMgr::loadCachedProgramBinary(LLGLSLShader* shader) +{ +	if (!mShaderCacheEnabled) return false; + +	glProgramParameteri(shader->mProgramObject, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + +	auto binary_iter = mShaderBinaryCache.find(shader->mShaderHash); +	if (binary_iter != mShaderBinaryCache.end()) +	{ +		std::string in_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin"); +		auto& shader_info = binary_iter->second; +		if (shader_info.mBinaryLength > 0) +		{ +			std::vector<U8> in_data; +			in_data.resize(shader_info.mBinaryLength); + +			LLUniqueFile filep = LLFile::fopen(in_path, "rb"); +			if (filep) +			{ +				size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep); +				filep.close(); + +				if (result == in_data.size()) +				{ +					GLenum error = glGetError(); // Clear current error +					glProgramBinary(shader->mProgramObject, shader_info.mBinaryFormat, in_data.data(), shader_info.mBinaryLength); + +					error = glGetError(); +					GLint success = GL_TRUE; +					glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success); +					if (error == GL_NO_ERROR && success == GL_TRUE) +					{ +						binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds(); +						LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL; +						return true; +					} +				} +			} +		} +		//an error occured, normally we would print log but in this case it means the shader needs recompiling. +		LL_INFOS() << "Failed to load cached binary for shader: " << shader->mName << " falling back to compilation" << LL_ENDL; +		LLFile::remove(in_path); +		mShaderBinaryCache.erase(binary_iter); +	} +	return false; +} + +bool LLShaderMgr::saveCachedProgramBinary(LLGLSLShader* shader) +{ +	if (!mShaderCacheEnabled) return true; + +	ProgramBinaryData binary_info = ProgramBinaryData(); +	glGetProgramiv(shader->mProgramObject, GL_PROGRAM_BINARY_LENGTH, &binary_info.mBinaryLength); +	if (binary_info.mBinaryLength > 0) +	{ +		std::vector<U8> program_binary; +		program_binary.resize(binary_info.mBinaryLength); + +		GLenum error = glGetError(); // Clear current error +		glGetProgramBinary(shader->mProgramObject, program_binary.size() * sizeof(U8), nullptr, &binary_info.mBinaryFormat, program_binary.data()); +		error = glGetError(); +		if (error == GL_NO_ERROR) +		{ +			std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin"); +			LLUniqueFile outfile = LLFile::fopen(out_path, "wb"); +			if (outfile) +			{ +				fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile); +				outfile.close(); + +				binary_info.mLastUsedTime = LLTimer::getTotalSeconds(); + +				mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info); +				return true; +			} +		} +	} +	return false; +} +  //virtual  void LLShaderMgr::initAttribsAndUniforms()  { diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 3da7a2a5f3..8c19c80cb0 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -302,7 +302,7 @@ public:      void dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text);  	BOOL	linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE);  	BOOL	validateProgramObject(GLuint obj); -	GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1); +	GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);  	// Implemented in the application to actually point to the shader directory.  	virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual @@ -310,6 +310,13 @@ public:  	// Implemented in the application to actually update out of date uniforms for a particular shader  	virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual +    void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version); +    void clearShaderCache(); +    void persistShaderCacheMetadata(); + +    bool loadCachedProgramBinary(LLGLSLShader* shader); +    bool saveCachedProgramBinary(LLGLSLShader* shader); +  public:  	// Map of shader names to compiled      std::map<std::string, GLuint> mVertexShaderObjects; @@ -320,8 +327,16 @@ public:  	std::vector<std::string> mReservedUniforms; -	//preprocessor definitions (name/value) -	std::map<std::string, std::string> mDefinitions; +    struct ProgramBinaryData +    { +        GLsizei mBinaryLength = 0; +        GLenum mBinaryFormat = 0; +        F32 mLastUsedTime = 0.0; +    }; +    std::map<LLUUID, ProgramBinaryData> mShaderBinaryCache; +    bool mShaderCacheInitialized = false; +    bool mShaderCacheEnabled = false; +    std::string mShaderCacheDir;  protected: diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index dd0ea0096c..b5dda23828 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -699,6 +699,16 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of  			}  		} +        LLVector4a* v = (LLVector4a*)mMappedData; + +        for (U32 i = start; i <= end; ++i) +        { +            if (!v->isFinite3()) +            { +                LL_ERRS() << "Non-finite vertex position data detected." << LL_ENDL; +            } +        } +  		LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;  		if (shader && shader->mFeatures.mIndexedTextureChannels > 1) | 
