FIRE-30559 Preview texture priority handling to give better response
parent
76b963a2ee
commit
18e3791bb2
|
|
@ -1006,9 +1006,13 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
|
|||
|
||||
void LLPreviewTexture::loadAsset()
|
||||
{
|
||||
mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
|
||||
mImageOldBoostLevel = mImage->getBoostLevel();
|
||||
mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
|
||||
// <FS:Beq> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
// mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
|
||||
// mImageOldBoostLevel = mImage->getBoostLevel();
|
||||
// mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
|
||||
mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE);
|
||||
mImageOldBoostLevel = LLGLTexture::BOOST_NONE;
|
||||
// </FS:Beq>
|
||||
mImage->forceToSaveRawImage(0) ;
|
||||
// <FS:Techwolf Lupindo> texture comment decoder
|
||||
mImage->setLoadedCallback(LLPreviewTexture::onTextureLoaded, 0, TRUE, FALSE, this, &mCallbackTextureList);
|
||||
|
|
|
|||
|
|
@ -1696,6 +1696,8 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
|
|||
mNeedsAux = FALSE;
|
||||
destroyRawImage();
|
||||
}
|
||||
// <FS:Beq/> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
gTextureList.recalcImageDecodePriority(this);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -710,6 +710,8 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy
|
|||
addImageToList(new_image);
|
||||
mUUIDMap[key] = new_image;
|
||||
new_image->setTextureListType(tex_type);
|
||||
// <FS:Beq/> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
gTextureList.recalcImageDecodePriority(new_image);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -721,6 +723,9 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
|
|||
{
|
||||
mCallbackList.erase(image);
|
||||
}
|
||||
// <FS:Beq/> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
mImagesWithChangedPriorities.erase(image);
|
||||
|
||||
LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType());
|
||||
llverify(mUUIDMap.erase(key) == 1);
|
||||
sNumImages--;
|
||||
|
|
@ -855,121 +860,252 @@ void LLViewerTextureList::clearFetchingRequests()
|
|||
}
|
||||
}
|
||||
|
||||
// <FS:Beq> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
// NOTE: previous version retained as single block comment, changes extend to the end of updateOneImageDecodePriority
|
||||
// void LLViewerTextureList::updateImagesDecodePriorities()
|
||||
// {
|
||||
// // Update the decode priority for N images each frame
|
||||
// {
|
||||
// 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
|
||||
|
||||
// //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon.
|
||||
// bool reset_timer = gViewerWindow->getProgressView()->getVisible();
|
||||
|
||||
// static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
|
||||
// const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
|
||||
// S32 update_counter = llmin(max_update_count, mUUIDMap.size());
|
||||
// uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
|
||||
// while ((update_counter-- > 0) && !mUUIDMap.empty())
|
||||
// {
|
||||
// if (iter == mUUIDMap.end())
|
||||
// {
|
||||
// iter = mUUIDMap.begin();
|
||||
// }
|
||||
// mLastUpdateKey = iter->first;
|
||||
// LLPointer<LLViewerFetchedTexture> imagep = iter->second;
|
||||
// ++iter; // safe to increment now
|
||||
|
||||
// if(imagep->isInDebug() || imagep->isUnremovable())
|
||||
// {
|
||||
// update_counter--;
|
||||
// continue; //is in debug, ignore.
|
||||
// }
|
||||
|
||||
// //
|
||||
// // Flush formatted images using a lazy flush
|
||||
// //
|
||||
// S32 num_refs = imagep->getNumRefs();
|
||||
// if (num_refs == min_refs)
|
||||
// {
|
||||
// if(reset_timer)
|
||||
// {
|
||||
// imagep->getLastReferencedTimer()->reset();
|
||||
// }
|
||||
// else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
|
||||
// {
|
||||
// // Remove the unused image from the image list
|
||||
// deleteImage(imagep);
|
||||
// imagep = NULL; // should destroy the image
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if(imagep->hasSavedRawImage())
|
||||
// {
|
||||
// if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
|
||||
// {
|
||||
// imagep->destroySavedRawImage() ;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if(imagep->isDeleted())
|
||||
// {
|
||||
// continue ;
|
||||
// }
|
||||
// else if(imagep->isDeletionCandidate())
|
||||
// {
|
||||
// imagep->destroyTexture() ;
|
||||
// continue ;
|
||||
// }
|
||||
// else if(imagep->isInactive())
|
||||
// {
|
||||
// if(reset_timer)
|
||||
// {
|
||||
// imagep->getLastReferencedTimer()->reset();
|
||||
// }
|
||||
// else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
|
||||
// {
|
||||
// imagep->setDeletionCandidate() ;
|
||||
// }
|
||||
// continue ;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// imagep->getLastReferencedTimer()->reset();
|
||||
|
||||
// //reset texture state.
|
||||
// imagep->setInactive() ;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (!imagep->isInImageList())
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// if(imagep->isInFastCacheList())
|
||||
// {
|
||||
// continue; //wait for loading from the fast cache.
|
||||
// }
|
||||
|
||||
// imagep->processTextureStats();
|
||||
// F32 old_priority = imagep->getDecodePriority();
|
||||
// F32 old_priority_test = llmax(old_priority, 0.0f);
|
||||
// F32 decode_priority = imagep->calcDecodePriority();
|
||||
// F32 decode_priority_test = llmax(decode_priority, 0.0f);
|
||||
// // Ignore < 20% difference
|
||||
// if ((decode_priority_test < old_priority_test * .8f) ||
|
||||
// (decode_priority_test > old_priority_test * 1.25f))
|
||||
// {
|
||||
// mImageList.erase(imagep) ;
|
||||
// imagep->setDecodePriority(decode_priority);
|
||||
// mImageList.insert(imagep);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void LLViewerTextureList::recalcImageDecodePriority(LLPointer<LLViewerFetchedTexture> image)
|
||||
{
|
||||
mImagesWithChangedPriorities.insert(image);
|
||||
}
|
||||
|
||||
void LLViewerTextureList::updateImagesDecodePriorities()
|
||||
{
|
||||
// Update the decode priority for N images each frame
|
||||
static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
|
||||
const size_t max_update_count = llmin((S32)(MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
|
||||
S32 update_counter = llmin(max_update_count, (mImagesWithChangedPriorities.size() + mUUIDMap.size()));
|
||||
|
||||
// First, process images whose decode priorities may have changed recently
|
||||
image_list_t::iterator iter2 = mImagesWithChangedPriorities.begin();
|
||||
while ((update_counter-- > 0) && (iter2 != mImagesWithChangedPriorities.end()))
|
||||
{
|
||||
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
|
||||
LLPointer<LLViewerFetchedTexture> imagep = *iter2;
|
||||
iter2 = mImagesWithChangedPriorities.erase(iter2);
|
||||
updateOneImageDecodePriority(imagep);
|
||||
}
|
||||
|
||||
//reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon.
|
||||
bool reset_timer = gViewerWindow->getProgressView()->getVisible();
|
||||
|
||||
static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
|
||||
const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
|
||||
S32 update_counter = llmin(max_update_count, mUUIDMap.size());
|
||||
uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
|
||||
while ((update_counter-- > 0) && !mUUIDMap.empty())
|
||||
// Second, process all of the images
|
||||
uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
|
||||
while ((update_counter-- > 0) && !mUUIDMap.empty())
|
||||
{
|
||||
if (iter == mUUIDMap.end())
|
||||
{
|
||||
if (iter == mUUIDMap.end())
|
||||
{
|
||||
iter = mUUIDMap.begin();
|
||||
}
|
||||
mLastUpdateKey = iter->first;
|
||||
LLPointer<LLViewerFetchedTexture> imagep = iter->second;
|
||||
++iter; // safe to increment now
|
||||
|
||||
if(imagep->isInDebug() || imagep->isUnremovable())
|
||||
{
|
||||
update_counter--;
|
||||
continue; //is in debug, ignore.
|
||||
}
|
||||
|
||||
//
|
||||
// Flush formatted images using a lazy flush
|
||||
//
|
||||
S32 num_refs = imagep->getNumRefs();
|
||||
if (num_refs == min_refs)
|
||||
{
|
||||
if(reset_timer)
|
||||
{
|
||||
imagep->getLastReferencedTimer()->reset();
|
||||
}
|
||||
else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
|
||||
{
|
||||
// Remove the unused image from the image list
|
||||
deleteImage(imagep);
|
||||
imagep = NULL; // should destroy the image
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(imagep->hasSavedRawImage())
|
||||
{
|
||||
if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
|
||||
{
|
||||
imagep->destroySavedRawImage() ;
|
||||
}
|
||||
}
|
||||
|
||||
if(imagep->isDeleted())
|
||||
{
|
||||
continue ;
|
||||
}
|
||||
else if(imagep->isDeletionCandidate())
|
||||
{
|
||||
imagep->destroyTexture() ;
|
||||
continue ;
|
||||
}
|
||||
else if(imagep->isInactive())
|
||||
{
|
||||
if(reset_timer)
|
||||
{
|
||||
imagep->getLastReferencedTimer()->reset();
|
||||
}
|
||||
else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
|
||||
{
|
||||
imagep->setDeletionCandidate() ;
|
||||
}
|
||||
continue ;
|
||||
}
|
||||
else
|
||||
{
|
||||
imagep->getLastReferencedTimer()->reset();
|
||||
|
||||
//reset texture state.
|
||||
imagep->setInactive() ;
|
||||
}
|
||||
}
|
||||
|
||||
if (!imagep->isInImageList())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(imagep->isInFastCacheList())
|
||||
{
|
||||
continue; //wait for loading from the fast cache.
|
||||
}
|
||||
|
||||
imagep->processTextureStats();
|
||||
F32 old_priority = imagep->getDecodePriority();
|
||||
F32 old_priority_test = llmax(old_priority, 0.0f);
|
||||
F32 decode_priority = imagep->calcDecodePriority();
|
||||
F32 decode_priority_test = llmax(decode_priority, 0.0f);
|
||||
// Ignore < 20% difference
|
||||
if ((decode_priority_test < old_priority_test * .8f) ||
|
||||
(decode_priority_test > old_priority_test * 1.25f))
|
||||
{
|
||||
mImageList.erase(imagep) ;
|
||||
imagep->setDecodePriority(decode_priority);
|
||||
mImageList.insert(imagep);
|
||||
}
|
||||
iter = mUUIDMap.begin();
|
||||
}
|
||||
mLastUpdateKey = iter->first;
|
||||
LLPointer<LLViewerFetchedTexture> imagep = iter->second;
|
||||
++iter; // safe to increment now
|
||||
updateOneImageDecodePriority(imagep);
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerTextureList::updateOneImageDecodePriority(LLPointer<LLViewerFetchedTexture> imagep)
|
||||
{
|
||||
const F32 lazy_flush_timeout = 30.f; // stop decoding
|
||||
const F32 max_inactive_time = 20.f; // actually delete
|
||||
const S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
|
||||
|
||||
bool reset_timer = gViewerWindow->getProgressView()->getVisible();
|
||||
|
||||
if(imagep->isInDebug() || imagep->isUnremovable())
|
||||
{
|
||||
return; //is in debug, ignore.
|
||||
}
|
||||
//
|
||||
// Flush formatted images using a lazy flush
|
||||
//
|
||||
S32 num_refs = imagep->getNumRefs();
|
||||
if (num_refs == min_refs)
|
||||
{
|
||||
if(reset_timer)
|
||||
{
|
||||
imagep->getLastReferencedTimer()->reset();
|
||||
}
|
||||
else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
|
||||
{
|
||||
// Remove the unused image from the image list
|
||||
deleteImage(imagep);
|
||||
imagep = NULL; // should destroy the image
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(imagep->hasSavedRawImage())
|
||||
{
|
||||
if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
|
||||
{
|
||||
imagep->destroySavedRawImage() ;
|
||||
}
|
||||
}
|
||||
|
||||
if(imagep->isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(imagep->isDeletionCandidate())
|
||||
{
|
||||
imagep->destroyTexture() ;
|
||||
return;
|
||||
}
|
||||
else if(imagep->isInactive())
|
||||
{
|
||||
if(reset_timer)
|
||||
{
|
||||
imagep->getLastReferencedTimer()->reset();
|
||||
}
|
||||
else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
|
||||
{
|
||||
imagep->setDeletionCandidate() ;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
imagep->getLastReferencedTimer()->reset();
|
||||
//reset texture state.
|
||||
imagep->setInactive() ;
|
||||
}
|
||||
}
|
||||
if (!imagep->isInImageList())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(imagep->isInFastCacheList())
|
||||
{
|
||||
return; //wait for loading from the fast cache.
|
||||
}
|
||||
|
||||
imagep->processTextureStats();
|
||||
F32 old_priority = imagep->getDecodePriority();
|
||||
F32 old_priority_test = llmax(old_priority, 0.0f);
|
||||
F32 decode_priority = imagep->calcDecodePriority();
|
||||
F32 decode_priority_test = llmax(decode_priority, 0.0f);
|
||||
// Ignore < 20% difference
|
||||
if ((decode_priority_test < old_priority_test * .8f) ||
|
||||
(decode_priority_test > old_priority_test * 1.25f))
|
||||
{
|
||||
mImageList.erase(imagep) ;
|
||||
imagep->setDecodePriority(decode_priority);
|
||||
mImageList.insert(imagep);
|
||||
}
|
||||
}
|
||||
// </FS:Beq> FIRE-30559
|
||||
|
||||
void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level)
|
||||
{
|
||||
if(!tex->setDebugFetching(debug_level))
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llui.h"
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
#include "lluiimage.h"
|
||||
|
||||
const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128;
|
||||
|
|
@ -147,6 +148,8 @@ public:
|
|||
|
||||
private:
|
||||
void updateImagesDecodePriorities();
|
||||
// <FS:Beq/> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
void updateOneImageDecodePriority(LLPointer<LLViewerFetchedTexture> imagep);
|
||||
F32 updateImagesCreateTextures(F32 max_time);
|
||||
F32 updateImagesFetchTextures(F32 max_time);
|
||||
void updateImagesUpdateStats();
|
||||
|
|
@ -219,7 +222,12 @@ public:
|
|||
|
||||
// <FS:Ansariel> Fast cache stats
|
||||
static U32 sNumFastCacheReads;
|
||||
|
||||
// <FS:Beq> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
// Recalculate the image's Decode Priority.
|
||||
// (We'll get to the image eventually even if this method isn't called, but this way it goes
|
||||
// to the head(-ish) of the line.)
|
||||
void recalcImageDecodePriority(LLPointer<LLViewerFetchedTexture> image);
|
||||
// </FS:Beq>
|
||||
private:
|
||||
typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
|
||||
uuid_map_t mUUIDMap;
|
||||
|
|
@ -228,7 +236,11 @@ private:
|
|||
|
||||
typedef std::set<LLPointer<LLViewerFetchedTexture>, LLViewerFetchedTexture::Compare> image_priority_list_t;
|
||||
image_priority_list_t mImageList;
|
||||
|
||||
// <FS:Beq> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
// Images that should be handled first in updateImagesDecodePriorities()
|
||||
image_list_t mImagesWithChangedPriorities;
|
||||
// </FS:Beq>
|
||||
|
||||
// simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon
|
||||
std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue