#2315 Ensure textures are deleted when they are no longer referenced. (#2343)

* #2315 WIP -- Clean up deletion rules in texture list.  Incidental decruft.

* Touch up assertions.

* Move mLastReferencedTimer to LLViewerMediaTexture since it's no longer used by LLViewerTexture
master
Dave Parks 2024-08-20 06:59:07 -05:00 committed by GitHub
parent 16c9c47f14
commit ed6732eda8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 26 additions and 174 deletions

View File

@ -82,8 +82,6 @@ public:
typedef enum
{
DELETED = 0, //removed from memory
DELETION_CANDIDATE, //ready to be removed from memory
INACTIVE, //not be used for the last certain period (i.e., 30 seconds).
ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
NO_DELETE = 99 //stay in memory, can not be removed.
} LLGLTextureState;

View File

@ -357,7 +357,9 @@ void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
if (obj->mGLTFAsset)
{ // object already has a GLTF asset, don't reload it
llassert(std::find(mObjects.begin(), mObjects.end(), obj) != mObjects.end());
// TODO: below assertion fails on dupliate requests for assets -- possibly need to touch up asset loading state machine
// llassert(std::find(mObjects.begin(), mObjects.end(), obj) != mObjects.end());
return;
}

View File

@ -408,8 +408,6 @@ extern LLVector3 gRelativeWindVec;
extern U32 gPacketsIn;
extern bool gPrintMessagesThisFrame;
extern LLUUID gBlackSquareID;
extern bool gRandomizeFramerate;
extern bool gPeriodicSlowFrame;

View File

@ -62,8 +62,6 @@ S32 LLDrawPoolAvatar::sShadowPass = -1;
S32 LLDrawPoolAvatar::sDiffuseChannel = 0;
F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f;
LLUUID gBlackSquareID;
static bool is_deferred_render = false;
static bool is_post_deferred_render = false;

View File

@ -357,8 +357,6 @@ void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
return;
}
llassert(mTexture[ch].notNull());
if (ch == LLRender::DIFFUSE_MAP)
{
getViewerObject()->changeTEImage(mTEOffset, new_texture) ;

View File

@ -836,7 +836,7 @@ void LLTextureView::draw()
for (LLViewerTextureList::image_list_t::iterator iter = gTextureList.mImageList.begin();
iter != gTextureList.mImageList.end(); )
{
LLPointer<LLViewerFetchedTexture> imagep = *iter++;
LLViewerFetchedTexture* imagep = *iter++;
if(!imagep->hasFetcher())
{
continue ;

View File

@ -1083,8 +1083,6 @@ void LLViewerFetchedTexture::init(bool firstinit)
mKeptSavedRawImageTime = 0.f;
mLastCallBackActiveTime = 0.f;
mForceCallbackFetch = false;
mInDebug = false;
mUnremovable = false;
mFTType = FTT_UNKNOWN;
}
@ -1234,32 +1232,6 @@ bool LLViewerFetchedTexture::isDeleted()
return mTextureState == DELETED;
}
bool LLViewerFetchedTexture::isInactive()
{
return mTextureState == INACTIVE;
}
bool LLViewerFetchedTexture::isDeletionCandidate()
{
return mTextureState == DELETION_CANDIDATE;
}
void LLViewerFetchedTexture::setDeletionCandidate()
{
if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE))
{
mTextureState = DELETION_CANDIDATE;
}
}
//set the texture inactive
void LLViewerFetchedTexture::setInactive()
{
if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently())
{
mTextureState = INACTIVE;
}
}
bool LLViewerFetchedTexture::isFullyLoaded() const
{
@ -1778,20 +1750,6 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
return current_discard;
}
bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level)
{
if(debug_level < 0)
{
mInDebug = false;
return false;
}
mInDebug = true;
mDesiredDiscardLevel = debug_level;
return true;
}
bool LLViewerFetchedTexture::isActiveFetching()
{
static LLCachedControl<bool> monitor_enabled(gSavedSettings,"DebugShowTextureInfo");

View File

@ -146,8 +146,6 @@ public:
virtual F32 getMaxVirtualSize() ;
LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
S32 getFullWidth() const { return mFullWidth; }
S32 getFullHeight() const { return mFullHeight; }
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
@ -197,7 +195,6 @@ protected:
mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need?
mutable S32 mMaxVirtualSizeResetCounter;
mutable S32 mMaxVirtualSizeResetInterval;
LLFrameTimer mLastReferencedTimer;
ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture
U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS];
@ -339,11 +336,6 @@ public:
void setBoostLevel(S32 level) override;
bool updateFetch();
bool setDebugFetching(S32 debug_level);
bool isInDebug() const { return mInDebug; }
void setUnremovable(bool value) { mUnremovable = value; }
bool isUnremovable() const { return mUnremovable; }
void clearFetchedResults(); //clear all fetched results, for debug use.
@ -378,10 +370,6 @@ public:
const std::string& getUrl() const {return mUrl;}
//---------------
bool isDeleted() ;
bool isInactive() ;
bool isDeletionCandidate();
void setDeletionCandidate() ;
void setInactive() ;
bool getUseDiscard() const { return mUseMipMaps && !mDontDiscard; }
//---------------
@ -434,8 +422,6 @@ private:
private:
bool mFullyLoaded;
bool mInDebug;
bool mUnremovable;
bool mInFastCacheList;
bool mForceCallbackFetch;
@ -586,6 +572,10 @@ public:
/*virtual*/ void removeFace(U32 ch, LLFace* facep) ;
/*virtual*/ F32 getMaxVirtualSize() ;
// get the timer that tracks the last time reinit was called
LLFrameTimer* getLastReferencedTimer() { return &mLastReferencedTimer; }
private:
void switchTexture(U32 ch, LLFace* facep) ;
bool findFaces() ;
@ -606,6 +596,9 @@ private:
bool mIsPlaying ;
U32 mUpdateVirtualSizeTime ;
// tracks last time reinit was called
LLFrameTimer mLastReferencedTimer;
public:
static void updateClass() ;
static void cleanUpClass() ;

View File

@ -187,13 +187,6 @@ void LLViewerTextureList::doPreloadImages()
image->setAddressMode(LLTexUnit::TAM_CLAMP);
mImagePreloads.insert(image);
}
LLPointer<LLImageRaw> img_blak_square_tex(new LLImageRaw(2, 2, 3));
memset(img_blak_square_tex->getData(), 0, img_blak_square_tex->getDataSize());
LLPointer<LLViewerFetchedTexture> img_blak_square(new LLViewerFetchedTexture(img_blak_square_tex, FTT_DEFAULT, false));
gBlackSquareID = img_blak_square->getID();
img_blak_square->setUnremovable(true);
addImage(img_blak_square, TEX_LIST_STANDARD);
}
static std::string get_texture_list_name()
@ -725,6 +718,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
size_t count = 0;
if (image->isInImageList())
{
image->setInImageList(false);
count = mImageList.erase(image) ;
if(count != 1)
{
@ -761,8 +755,6 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
<< LL_ENDL;
}
}
image->setInImageList(false) ;
}
void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListType tex_type)
@ -808,15 +800,6 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void LLViewerTextureList::dirtyImage(LLViewerFetchedTexture *image)
{
mDirtyTextureList.insert(image);
}
////////////////////////////////////////////////////////////////////////////
void LLViewerTextureList::updateImages(F32 max_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@ -857,12 +840,6 @@ void LLViewerTextureList::updateImages(F32 max_time)
//handle results from decode threads
updateImagesCreateTextures(remaining_time);
if (!mDirtyTextureList.empty())
{
gPipeline.dirtyPoolObjectTextures(mDirtyTextureList);
mDirtyTextureList.clear();
}
bool didone = false;
for (image_list_t::iterator iter = mCallbackList.begin();
iter != mCallbackList.end(); )
@ -906,12 +883,6 @@ extern bool gCubeSnapshot;
void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep, bool flush_images)
{
if (imagep->isInDebug() || imagep->isUnremovable())
{
//update_counter--;
return; //is in debug, ignore.
}
llassert(!gCubeSnapshot);
static LLCachedControl<F32> bias_distance_scale(gSavedSettings, "TextureBiasDistanceScale", 1.f);
@ -926,7 +897,6 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
bool onFace = false;
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
@ -935,7 +905,6 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
if (face && face->getViewerObject())
{
onFace = true;
F32 radius;
F32 cos_angle_to_view_dir;
static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f);
@ -983,24 +952,17 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
volume->updateSpotLightPriority();
}
//imagep->setDebugText(llformat("%.3f - %d", sqrtf(imagep->getMaxVirtualSize()), imagep->getBoostLevel()));
F32 lazy_flush_timeout = 30.f; // stop decoding
F32 max_inactive_time = 20.f; // actually delete
S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
F32 max_inactive_time = 20.f; // inactive time before deleting saved raw image
S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, and 1 for "entries" in updateImagesFetchTextures
//
// Flush formatted images using a lazy flush
//
S32 num_refs = imagep->getNumRefs();
if (num_refs == min_refs && flush_images)
if (num_refs <= min_refs && flush_images)
{
if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
{
// Remove the unused image from the image list
deleteImage(imagep);
imagep = NULL; // should destroy the image
}
// Remove the unused image from the image list
deleteImage(imagep);
return;
}
else
@ -1017,27 +979,6 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
{
return;
}
else if (imagep->isDeletionCandidate())
{
imagep->destroyTexture();
return;
}
else if (imagep->isInactive())
{
if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
{
imagep->setDeletionCandidate();
}
return;
}
else
{
imagep->getLastReferencedTimer()->reset();
//reset texture state.
if(!onFace)
imagep->setInactive();
}
}
if (!imagep->isInImageList())
@ -1052,20 +993,6 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
imagep->processTextureStats();
}
void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(!tex->setDebugFetching(debug_level))
{
return;
}
const F32 DEBUG_PRIORITY = 100000.f;
removeImageFromList(tex);
tex->mMaxVirtualSize = DEBUG_PRIORITY;
addImageToList(tex);
}
F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@ -1169,21 +1096,12 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(!imagep)
if(!imagep || gCubeSnapshot)
{
return ;
}
if(imagep->isInImageList())
{
removeImageFromList(imagep);
}
if (!gCubeSnapshot)
{ // never call processTextureStats in a cube snapshot
imagep->processTextureStats();
}
imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;
addImageToList(imagep);
imagep->processTextureStats();
return ;
}
@ -1198,12 +1116,15 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
// update N textures at beginning of mImageList
U32 update_count = 0;
static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinCount"); // default: 32
// WIP -- dumb code here
// NOTE: a texture may be deleted as a side effect of some of these updates
// Deletion rules check ref count, so be careful not to hold any LLPointer references to the textures here other than the one in entries.
//update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater
update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20);
update_count = llmin(update_count, (U32) mUUIDMap.size());
{
{ // copy entries out of UUID map to avoid iterator invalidation from deletion inside updateImageDecodeProiroty or updateFetch below
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vtluift - copy");
// copy entries out of UUID map for updating
@ -1226,30 +1147,22 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
LLTimer timer;
LLPointer<LLViewerTexture> last_imagep = nullptr;
for (auto& imagep : entries)
{
if (imagep->getNumRefs() > 1) // make sure this image hasn't been deleted before attempting to update (may happen as a side effect of some other image updating)
mLastUpdateKey = LLTextureKey(imagep->getID(), (ETexListType)imagep->getTextureListType());
if (imagep->getNumRefs() > 1) // make sure this image hasn't been deleted before attempting to update (may happen as a side effect of some other image updating)
{
updateImageDecodePriority(imagep);
imagep->updateFetch();
}
last_imagep = imagep;
if (timer.getElapsedTimeF32() > max_time)
{
break;
}
}
if (last_imagep)
{
mLastUpdateKey = LLTextureKey(last_imagep->getID(), (ETexListType)last_imagep->getTextureListType());
}
return timer.getElapsedTimeF32();
}

View File

@ -122,8 +122,6 @@ public:
LLViewerFetchedTexture *findImage(const LLUUID &image_id, ETexListType tex_type);
LLViewerFetchedTexture *findImage(const LLTextureKey &search_key);
void dirtyImage(LLViewerFetchedTexture *image);
// Using image stats, determine what images are necessary, and perform image updates.
void updateImages(F32 max_time);
void forceImmediateUpdate(LLViewerFetchedTexture* imagep) ;
@ -142,7 +140,6 @@ public:
void doPrefetchImages();
void clearFetchingRequests();
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
// do some book keeping on the specified texture
// - updates decode priority
@ -223,9 +220,6 @@ public:
image_list_t mCallbackList;
image_list_t mFastCacheList;
// Note: just raw pointers because they are never referenced, just compared against
std::set<LLViewerFetchedTexture*> mDirtyTextureList;
bool mForceResetTextureStats;
// to make "for (auto& imagep : gTextureList)" work