diff options
| author | Dave Parks <davep@lindenlab.com> | 2021-10-21 21:19:48 +0000 | 
|---|---|---|
| committer | Dave Parks <davep@lindenlab.com> | 2021-10-21 21:19:48 +0000 | 
| commit | e774bffb28a71730792931aeb1ed6a46d3cfe67b (patch) | |
| tree | d82248f9fc0678fb5e6e3c39f5d0011707b0a86c | |
| parent | 6ecf8f2c01dc90c26a8a0ccbd11abc2241debfa9 (diff) | |
SL-16202 Fix for textures appearing black or flashing white due to optimization bugs.
| -rw-r--r-- | indra/llcommon/workqueue.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 241 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.h | 16 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 14 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 2 | ||||
| -rw-r--r-- | indra/newview/llglsandbox.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.cpp | 13 | 
7 files changed, 141 insertions, 150 deletions
| diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index ffc9a97dc0..b32357e832 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -54,6 +54,7 @@ void LL::WorkQueue::runUntilClose()  bool LL::WorkQueue::runPending()  { +    LL_PROFILE_ZONE_SCOPED;      for (Work work; mQueue.tryPop(work); )      {          callWork(work); @@ -110,6 +111,7 @@ void LL::WorkQueue::callWork(const Queue::DataTuple& work)  void LL::WorkQueue::callWork(const Work& work)  { +    LL_PROFILE_ZONE_SCOPED;      try      {          work(); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index aff29bd857..b5e1910242 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -683,7 +683,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)  }  static LLTrace::BlockTimerStatHandle FTM_SET_IMAGE("setImage"); -BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) +BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename)  {  	LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE);  	bool is_compressed = false; @@ -702,12 +702,11 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)          break;      } -	 -	  	if (mUseMipMaps)  	{  		//set has mip maps to true before binding image so tex parameters get set properly -		gGL.getTexUnit(0)->unbind(mBindTarget); +        gGL.getTexUnit(0)->unbind(mBindTarget); +          		mHasMipMaps = true;  		mTexOptionsDirty = true;  		setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); @@ -717,7 +716,8 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		mHasMipMaps = false;  	} -	llverify(gGL.getTexUnit(0)->bind(this)); +    gGL.getTexUnit(0)->bind(this, false, false, usename); +      if (mUseMipMaps)  	{ @@ -1211,7 +1211,7 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)  }  // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) +void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)  {  	if (gGLManager.mInited)  	{ @@ -1381,13 +1381,13 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  		return FALSE;  	} -	mGLTextureCreated = false ;  	llassert(gGLManager.mInited);  	stop_glerror();  	if (!imageraw || imageraw->isBufferInvalid())  	{  		LL_WARNS() << "Trying to create a texture from invalid image data" << LL_ENDL; +        mGLTextureCreated = false;  		return FALSE;  	} @@ -1407,6 +1407,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  	if (!setSize(w, h, imageraw->getComponents(), discard_level))  	{  		LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL; +        mGLTextureCreated = false;  		return FALSE;  	} @@ -1475,6 +1476,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  		destroyGLTexture();  		mCurrentDiscardLevel = discard_level;	  		mLastBindTime = sLastFrameTime; +        mGLTextureCreated = false;  		return TRUE ;  	} @@ -1486,104 +1488,123 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)");  BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)  { -	LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE3); -	llassert(data_in); -	stop_glerror(); - -	if (discard_level < 0) -	{ -		llassert(mCurrentDiscardLevel >= 0); -		discard_level = mCurrentDiscardLevel; -	} -	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); +    LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE3); +    llassert(data_in); +    stop_glerror(); -	if (mTexName != 0 && discard_level == mCurrentDiscardLevel) -	{ -		// This will only be true if the size has not changed -		return setImage(data_in, data_hasmips); -	} -	 -	U32 old_name = mTexName; -// 	S32 old_discard = mCurrentDiscardLevel; -	 -	if (usename != 0) -	{ -		mTexName = usename; -	} -	else -	{ -		LLImageGL::generateTextures(1, &mTexName); -		stop_glerror(); -		{ -			llverify(gGL.getTexUnit(0)->bind(this)); -			stop_glerror(); -			glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); -			stop_glerror(); -			glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL,  mMaxDiscardLevel-discard_level); -			stop_glerror(); -		} -	} -	if (!mTexName) -	{ -		if (old_name) -		{ -			sGlobalTextureMemory -= mTextureMemory; -			LLImageGL::deleteTextures(1, &old_name); -			disclaimMem(mTextureMemory); -			stop_glerror(); -		} +    if (discard_level < 0) +    { +        llassert(mCurrentDiscardLevel >= 0); +        discard_level = mCurrentDiscardLevel; +    } +    discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); -		LL_WARNS() << "LLImageGL::createGLTexture failed to make texture" << LL_ENDL; -		return FALSE; -	} +    if (mTexName != 0 && discard_level == mCurrentDiscardLevel) +    { +        // This will only be true if the size has not changed +        return setImage(data_in, data_hasmips); +    } -	if (mUseMipMaps) -	{ -		mAutoGenMips = gGLManager.mHasMipMapGeneration; +    GLuint old_texname = mTexName; +     +    if (usename != 0) +    { +        mNewTexName = usename; +    } +    else +    { +        LLImageGL::generateTextures(1, &mNewTexName); +        { +            gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); +            glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); +            glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); +        } +    } +     +    if (mUseMipMaps) +    { +        mAutoGenMips = gGLManager.mHasMipMapGeneration;  #if LL_DARWIN -		// On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. -		if(gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) -		{ -			mAutoGenMips = FALSE; -		} +        // On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. +        if (gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) +        { +            mAutoGenMips = FALSE; +        }  #endif -	} +    } -	mCurrentDiscardLevel = discard_level;	 +    mCurrentDiscardLevel = discard_level; -	if (!setImage(data_in, data_hasmips)) -	{ -		stop_glerror(); -		return FALSE; -	} +    if (!setImage(data_in, data_hasmips, mNewTexName)) +    { +        return FALSE; +    } -	// Set texture options to our defaults. -	gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); -	gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); -	gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); +    // Set texture options to our defaults. +    gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); +    gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); +    gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); -	// things will break if we don't unbind after creation -	gGL.getTexUnit(0)->unbind(mBindTarget); -	stop_glerror(); +    // things will break if we don't unbind after creation +    gGL.getTexUnit(0)->unbind(mBindTarget); -	if (old_name != 0) -	{ -		sGlobalTextureMemory -= mTextureMemory; +    if (old_texname != 0) +    { +        sGlobalTextureMemory -= mTextureMemory; +    } -		LLImageGL::deleteTextures(1, &old_name); +    //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread +    if (LLImageGLThread::sInstance != nullptr &&  +        LLThread::currentID() == LLImageGLThread::sInstance->getID()) +    { +        { +            LL_PROFILE_ZONE_NAMED("cglt - sync"); +            if (gGLManager.mHasSync) +            { +                auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +                glClientWaitSync(sync, 0, 0); +                glDeleteSync(sync); +            } +            else +            { +                glFinish(); +            } +        } -		stop_glerror(); -	} +        ref(); +        LLImageGLThread::sInstance->postCallback([=]() +            { +                LL_PROFILE_ZONE_NAMED("cglt - delete callback"); +                if (old_texname != 0) +                { +                    LLImageGL::deleteTextures(1, &old_texname); +                } +                mTexName = mNewTexName; +                mNewTexName = 0; +                unref(); +            }); +    } +    else  +    { +        //not on background thread, immediately set mTexName +        if (old_texname != 0) +        { +            LLImageGL::deleteTextures(1, &old_texname); +        } +        mTexName = mNewTexName; +        mNewTexName = 0; +    } +     +    disclaimMem(mTextureMemory); +    mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); +    claimMem(mTextureMemory); +    sGlobalTextureMemory += mTextureMemory; +    mTexelsInGLTexture = getWidth() * getHeight(); -	disclaimMem(mTextureMemory); -	mTextureMemory = (S32Bytes)getMipBytes(discard_level); -	claimMem(mTextureMemory); -	sGlobalTextureMemory += mTextureMemory; -	mTexelsInGLTexture = getWidth() * getHeight() ; +    // mark this as bound at this point, so we don't throw it out immediately +    mLastBindTime = sLastFrameTime; -	// mark this as bound at this point, so we don't throw it out immediately -	mLastBindTime = sLastFrameTime; -	return TRUE; +    return TRUE;  }  BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -2274,17 +2295,7 @@ bool LLImageGLThread::post(const std::function<void()>& func)  {      try      { -        if (mFunctionQueue.size() < mFunctionQueue.capacity()) -        { -            //NOTE: tryPushFront will return immediately if the lock is held -            // desired behavior here is to push and return true unless the  -            // queue is full or closed -            mFunctionQueue.pushFront(func); -        } -        else -        { -            return false; -        } +        mFunctionQueue.post(func);      }      catch (LLThreadSafeQueueInterrupt e)      { @@ -2300,7 +2311,7 @@ bool LLImageGLThread::postCallback(const std::function<void()>& callback)  {      try      { -        mCallbackQueue.pushFront(callback); +        mCallbackQueue.post(callback);      }      catch (LLThreadSafeQueueInterrupt e)      { @@ -2315,34 +2326,14 @@ void LLImageGLThread::executeCallbacks()  {      LL_PROFILE_ZONE_SCOPED;      //executed from main thread -    std::function<void()> callback; -    while (mCallbackQueue.tryPopBack(callback)) -    { -        LL_PROFILE_ZONE_NAMED("iglt - callback"); -        callback(); -    } +    mCallbackQueue.runPending();  }  void LLImageGLThread::run()  {      mWindow->makeContextCurrent(mContext);      gGL.init(); -    try -    { -        while (true) -        { -            LL_PROFILE_ZONE_SCOPED; -            std::function<void()> curFunc = mFunctionQueue.popBack(); -            { -                LL_PROFILE_ZONE_NAMED("iglt - function") -                    curFunc(); -            } -        } -    } -    catch (LLThreadSafeQueueInterrupt e) -    { -        //queue is closed, fall out of run loop -    } +    mFunctionQueue.runUntilClose();      gGL.shutdown();      mWindow->destroySharedContext(mContext);  } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 8e9b483c2d..da626a1093 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,6 +37,8 @@  #include "llunits.h"  #include "llthreadsafequeue.h"  #include "llrender.h" +#include "workqueue.h" +  class LLTextureAtlas ;  class LLWindow; @@ -50,7 +52,7 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL>  public:  	// These 2 functions replace glGenTextures() and glDeleteTextures()  	static void generateTextures(S32 numTextures, U32 *textures); -	static void deleteTextures(S32 numTextures, U32 *textures); +	static void deleteTextures(S32 numTextures, const U32 *textures);  	static void deleteDeadTextures();  	// Size calculation @@ -110,7 +112,7 @@ public:  		S32 category = sMaxCategories-1);  	BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0);  	void setImage(const LLImageRaw* imageraw); -	BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE); +	BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0);  	BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE);  	BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE);  	BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); @@ -210,8 +212,9 @@ private:  	bool     mGLTextureCreated ;  	LLGLuint mTexName; +    LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread  	U16      mWidth; -	U16      mHeight;	 +	U16      mHeight;  	S8       mCurrentDiscardLevel;  	S8       mDiscardLevelInAtlas; @@ -319,8 +322,11 @@ public:      void run() override; -    LLThreadSafeQueue<std::function<void()>> mFunctionQueue; -    LLThreadSafeQueue<std::function<void()>> mCallbackQueue; +    // Work Queue for background thread +    LL::WorkQueue mFunctionQueue; + +    // Work Queue for main thread (run from updateClass) +    LL::WorkQueue mCallbackQueue;      LLWindow* mWindow;      void* mContext; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 669a09d3ce..aad04beea2 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -236,6 +236,10 @@ void LLTexUnit::bindFast(LLTexture* texture)      glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);      gGL.mCurrTextureUnitIndex = mIndex;      mCurrTexture = gl_tex->getTexName(); +    if (!mCurrTexture) +    { +        mCurrTexture = LLImageGL::sDefaultGLTexture->getTexName(); +    }      glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);      mHasMipMaps = gl_tex->mHasMipMaps;  } @@ -306,18 +310,20 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  	return true;  } -bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) +bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 usename)  {  	stop_glerror();  	if (mIndex < 0) return false; +    U32 texname = usename ? usename : texture->getTexName(); +  	if(!texture)  	{  		LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;  		return false;  	} -	if(!texture->getTexName()) +	if(!texname)  	{  		if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName())  		{ @@ -327,7 +333,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)  		return false ;  	} -	if ((mCurrTexture != texture->getTexName()) || forceBind) +	if ((mCurrTexture != texname) || forceBind)  	{  		gGL.flush();  		stop_glerror(); @@ -335,7 +341,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)  		stop_glerror();  		enable(texture->getTarget());  		stop_glerror(); -		mCurrTexture = texture->getTexName(); +		mCurrTexture = texname;  		glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);  		stop_glerror();  		texture->updateBindStats(texture->mTextureMemory);		 diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 6e2647a16b..7f19a45410 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -158,7 +158,7 @@ public:  	// Binds the LLImageGL to this texture unit   	// (automatically enables the unit for the LLImageGL's texture type) -	bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false); +	bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false, S32 usename = 0);      bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);      // bind implementation for inner loops diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 0f288e05ca..91f314c115 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1090,7 +1090,7 @@ F32 gpu_benchmark()      delete [] pixels;  	//make a dummy triangle to draw with -	LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); +	LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, GL_STREAM_DRAW_ARB);  	if (!buff->allocateBuffer(3, 0, true))  	{ @@ -1100,7 +1100,6 @@ F32 gpu_benchmark()  	}  	LLStrider<LLVector3> v; -	LLStrider<LLVector2> tc;  	if (! buff->getVertexStrider(v))  	{ diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 949e71a4c9..34847d8618 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1637,19 +1637,6 @@ void LLViewerFetchedTexture::scheduleCreateTexture()              {                  //actually create the texture on a background thread                  createTexture(); -                { -                    LL_PROFILE_ZONE_NAMED("iglt - sync"); -                    if (gGLManager.mHasSync) -                    { -                        auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -                        glClientWaitSync(sync, 0, 0); -                        glDeleteSync(sync); -                    } -                    else -                    { -                        glFinish(); -                    } -                }                  LLImageGLThread::sInstance->postCallback([this]()                      {                          //finalize on main thread | 
