summaryrefslogtreecommitdiff
path: root/indra/newview/llviewertexturelist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewertexturelist.cpp')
-rw-r--r--indra/newview/llviewertexturelist.cpp407
1 files changed, 249 insertions, 158 deletions
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index c812504f9b..f174e16624 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -30,6 +30,7 @@
#include "llviewertexturelist.h"
+#include "llagent.h"
#include "llgl.h" // fot gathering stats from GL
#include "llimagegl.h"
#include "llimagebmp.h"
@@ -70,6 +71,8 @@ S32 LLViewerTextureList::sNumImages = 0;
LLViewerTextureList gTextureList;
+extern LLGLSLShader gCopyProgram;
+
ETexListType get_element_type(S32 priority)
{
return (priority == LLViewerFetchedTexture::BOOST_ICON || priority == LLViewerFetchedTexture::BOOST_THUMBNAIL) ? TEX_LIST_SCALE : TEX_LIST_STANDARD;
@@ -121,6 +124,9 @@ void LLViewerTextureList::doPreloadImages()
LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
LLUIImageList* image_list = LLUIImageList::getInstance();
+ // Set default particle texture
+ LLViewerFetchedTexture::sDefaultParticleImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+
// Set the default flat normal map
// BLANK_OBJECT_NORMAL has a version on dataserver, but it has compression artifacts
LLViewerFetchedTexture::sFlatNormalImagep =
@@ -195,13 +201,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()
@@ -278,7 +277,7 @@ void LLViewerTextureList::doPrefetchImages()
S32 pixel_area = imagesd["area"];
S32 texture_type = imagesd["type"];
- if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type)
+ if((LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type))
{
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type);
if (image)
@@ -306,7 +305,7 @@ void LLViewerTextureList::shutdown()
// Write out list of currently loaded textures for precaching on startup
typedef std::set<std::pair<S32,LLViewerFetchedTexture*> > image_area_list_t;
image_area_list_t image_area_list;
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* image = *iter;
@@ -362,8 +361,11 @@ void LLViewerTextureList::shutdown()
mCallbackList.clear();
// Flush all of the references
- mLoadingStreamList.clear();
- mCreateTextureList.clear();
+ while (!mCreateTextureList.empty())
+ {
+ mCreateTextureList.front()->mCreatePending = false;
+ mCreateTextureList.pop();
+ }
mFastCacheList.clear();
mUUIDMap.clear();
@@ -377,7 +379,7 @@ void LLViewerTextureList::dump()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LL_INFOS() << "LLViewerTextureList::dump()" << LL_ENDL;
- for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
+ for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
{
LLViewerFetchedTexture* image = *it;
@@ -391,15 +393,9 @@ void LLViewerTextureList::dump()
}
}
-void LLViewerTextureList::destroyGL(bool save_state)
+void LLViewerTextureList::destroyGL()
{
- LLImageGL::destroyGL(save_state);
-}
-
-void LLViewerTextureList::restoreGL()
-{
- llassert_always(mInitialized) ;
- LLImageGL::restoreGL();
+ LLImageGL::destroyGL();
}
/* Vertical tab container button image IDs
@@ -421,6 +417,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
const LLUUID& force_id)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LL_PROFILE_ZONE_TEXT(filename.c_str(), filename.size());
if(!mInitialized)
{
return NULL ;
@@ -736,6 +733,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
size_t count = 0;
if (image->isInImageList())
{
+ image->setInImageList(false);
count = mImageList.erase(image) ;
if(count != 1)
{
@@ -772,8 +770,6 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
<< LL_ENDL;
}
}
-
- image->setInImageList(false) ;
}
void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListType tex_type)
@@ -819,15 +815,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;
@@ -839,12 +826,21 @@ void LLViewerTextureList::updateImages(F32 max_time)
clearFetchingRequests();
gPipeline.clearRebuildGroups();
cleared = true;
+ return;
+ }
+ // ARRIVING is a delay to let things decode, cache and process,
+ // so process textures like normal despite gTeleportDisplay
+ if (gAgent.getTeleportState() != LLAgent::TELEPORT_ARRIVING)
+ {
+ return;
}
- return;
}
- cleared = false;
+ else
+ {
+ cleared = false;
+ }
- LLAppViewer::getTextureFetch()->setTextureBandwidth(LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED).value());
+ LLAppViewer::getTextureFetch()->setTextureBandwidth((F32)LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED).value());
{
using namespace LLStatViewer;
@@ -868,12 +864,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(); )
@@ -905,7 +895,7 @@ void LLViewerTextureList::clearFetchingRequests()
LLAppViewer::getTextureFetch()->deleteAllRequests();
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* imagep = *iter;
@@ -913,106 +903,167 @@ void LLViewerTextureList::clearFetchingRequests()
}
}
-static void touch_texture(LLViewerFetchedTexture* tex, F32 vsize)
-{
- if (tex)
- {
- tex->addTextureStats(vsize);
- }
-}
-
extern bool gCubeSnapshot;
-void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep)
+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);
- static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f);
- static LLCachedControl<F32> texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f);
+ constexpr F32 BIAS_TRS_OUT_OF_SCREEN = 1.5f;
+ constexpr F32 BIAS_TRS_ON_SCREEN = 1.f;
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE
+ if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures
{
+ static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.0095f);
+ static LLCachedControl<F32> texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f);
+
+ F32 max_vsize = 0.f;
+ bool on_screen = false;
+
+ U32 face_count = 0;
+
+ // get adjusted bias based on image resolution
+ LLImageGL* img = imagep->getGLTexture();
+ F32 max_discard = F32(img ? img->getMaxDiscardLevel() : MAX_DISCARD_LEVEL);
+ F32 bias = llclamp(max_discard - 2.f, 1.f, LLViewerTexture::sDesiredDiscardBias);
+
+ // convert bias into a vsize scaler
+ bias = (F32) llroundf(powf(4, bias - 1.f));
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
{
LLFace* face = (*(imagep->getFaceList(i)))[fi];
- if (face && face->getViewerObject() && face->getTextureEntry())
+ if (face && face->getViewerObject())
{
+ ++face_count;
+ F32 radius;
+ F32 cos_angle_to_view_dir;
+
+ if ((gFrameCount - face->mLastTextureUpdate) > 10)
+ { // only call calcPixelArea at most once every 10 frames for a given face
+ // this helps eliminate redundant calls to calcPixelArea for faces that have multiple textures
+ // assigned to them, such as is the case with GLTF materials or Blinn-Phong materials
+ face->mInFrustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
+ face->mLastTextureUpdate = gFrameCount;
+ }
+
F32 vsize = face->getPixelArea();
+ on_screen |= face->mInFrustum;
+
// Scale desired texture resolution higher or lower depending on texture scale
//
- // Minimum usage examples: a 1024x1024 texture with aplhabet, runing string
- // shows one letter at a time
+ // Minimum usage examples: a 1024x1024 texture with aplhabet (texture atlas),
+ // runing string shows one letter at a time. If texture has ten 100px symbols
+ // per side, minimal scale is (100/1024)^2 = 0.0095
//
// Maximum usage examples: huge chunk of terrain repeats texture
- const LLTextureEntry* te = face->getTextureEntry();
+ // TODO: make this work with the GLTF texture transforms
+ S32 te_offset = face->getTEOffset(); // offset is -1 if not inited
+ LLViewerObject* objp = face->getViewerObject();
+ const LLTextureEntry* te = (te_offset < 0 || te_offset >= objp->getNumTEs()) ? nullptr : objp->getTE(te_offset);
F32 min_scale = te ? llmin(fabsf(te->getScaleS()), fabsf(te->getScaleT())) : 1.f;
- min_scale = llclamp(min_scale*min_scale, texture_scale_min(), texture_scale_max());
-
+ min_scale = llclamp(min_scale * min_scale, texture_scale_min(), texture_scale_max());
vsize /= min_scale;
- vsize /= LLViewerTexture::sDesiredDiscardBias;
- vsize /= llmax(1.f, (LLViewerTexture::sDesiredDiscardBias-1.f) * (1.f + face->getDrawable()->mDistanceWRTCamera * bias_distance_scale));
- F32 radius;
- F32 cos_angle_to_view_dir;
- bool in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
- if (!in_frustum || !face->getDrawable()->isVisible())
- { // further reduce by discard bias when off screen or occluded
- vsize /= LLViewerTexture::sDesiredDiscardBias;
+ // apply bias to offscreen faces all the time, but only to onscreen faces when bias is large
+ // use mImportanceToCamera to make bias switch a bit more gradual
+ if (!face->mInFrustum || LLViewerTexture::sDesiredDiscardBias > 1.9f + face->mImportanceToCamera / 2.f)
+ {
+ vsize /= bias;
}
- // if a GLTF material is present, ignore that face
- // as far as this texture stats go, but update the GLTF material
- // stats
- LLFetchedGLTFMaterial* mat = te ? (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial() : nullptr;
- llassert(mat == nullptr || dynamic_cast<LLFetchedGLTFMaterial*>(te->getGLTFRenderMaterial()) != nullptr);
- if (mat)
+
+ // boost resolution of textures that are important to the camera
+ if (face->mInFrustum)
{
- touch_texture(mat->mBaseColorTexture, vsize);
- touch_texture(mat->mNormalTexture, vsize);
- touch_texture(mat->mMetallicRoughnessTexture, vsize);
- touch_texture(mat->mEmissiveTexture, vsize);
+ static LLCachedControl<F32> texture_camera_boost(gSavedSettings, "TextureCameraBoost", 8.f);
+ vsize *= llmax(face->mImportanceToCamera*texture_camera_boost, 1.f);
}
- else
+
+ max_vsize = llmax(max_vsize, vsize);
+
+ // addTextureStats limits size to sMaxVirtualSize
+ if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize
+ && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN))
{
- imagep->addTextureStats(vsize);
+ break;
}
}
}
+
+ if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize
+ && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN))
+ {
+ break;
+ }
+ }
+
+ if (face_count > 1024)
+ { // this texture is used in so many places we should just boost it and not bother checking its vsize
+ // this is especially important because the above is not time sliced and can hit multiple ms for a single texture
+ imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_HIGH);
+ // Do we ever remove it? This also sets texture nodelete!
}
+
+ if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE)
+ { // conditionally reset max virtual size for unboosted LOD_TEXTURES
+ // this is an alternative to decaying mMaxVirtualSize over time
+ // that keeps textures from continously downrezzing and uprezzing in the background
+
+ if (LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_OUT_OF_SCREEN ||
+ (!on_screen && LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_ON_SCREEN))
+ {
+ imagep->mMaxVirtualSize = 0.f;
+ }
+ }
+
+ imagep->addTextureStats(max_vsize);
+ }
+
+#if 0
+ imagep->setDebugText(llformat("%d/%d - %d/%d -- %d/%d",
+ (S32)sqrtf(max_vsize),
+ (S32)sqrtf(imagep->mMaxVirtualSize),
+ imagep->getDiscardLevel(),
+ imagep->getDesiredDiscardLevel(),
+ imagep->getWidth(),
+ imagep->getFullWidth()));
+#endif
+
+ // make sure to addTextureStats for any spotlights that are using this texture
+ for (S32 vi = 0; vi < imagep->getNumVolumes(LLRender::LIGHT_TEX); ++vi)
+ {
+ LLVOVolume* volume = (*imagep->getVolumeList(LLRender::LIGHT_TEX))[vi];
+ volume->updateSpotLightPriority();
}
- //imagep->setDebugText(llformat("%.3f - %d", sqrtf(imagep->getMaxVirtualSize()), imagep->getBoostLevel()));
+ 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
- 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 lazy_flush_timeout = 30.f; // delete unused images after 30 seconds
//
// Flush formatted images using a lazy flush
//
S32 num_refs = imagep->getNumRefs();
- if (num_refs == min_refs)
+ 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
+ return;
}
- return;
}
else
{
+ // still referenced outside of image list, reset timer
+ imagep->getLastReferencedTimer()->reset();
+
if (imagep->hasSavedRawImage())
{
if (imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
@@ -1025,26 +1076,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.
- imagep->setInactive();
- }
}
if (!imagep->isInImageList())
@@ -1059,20 +1090,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;
@@ -1084,22 +1101,85 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
//
LLTimer create_timer;
- image_list_t::iterator enditer = mCreateTextureList.begin();
- for (image_list_t::iterator iter = mCreateTextureList.begin();
- iter != mCreateTextureList.end();)
+
+ while (!mCreateTextureList.empty())
{
- image_list_t::iterator curiter = iter++;
- enditer = iter;
- LLViewerFetchedTexture *imagep = *curiter;
- imagep->createTexture();
+ LLViewerFetchedTexture* imagep = mCreateTextureList.front();
+ llassert(imagep->mCreatePending);
+
+ // desired discard may change while an image is being decoded. If the texture in VRAM is sufficient
+ // for the current desired discard level, skip the texture creation. This happens more often than it probably
+ // should
+ bool redundant_load = imagep->hasGLTexture() && imagep->getDiscardLevel() <= imagep->getDesiredDiscardLevel();
+
+ if (!redundant_load)
+ {
+ imagep->createTexture();
+ }
+
imagep->postCreateTexture();
+ imagep->mCreatePending = false;
+ mCreateTextureList.pop();
+
+ if (imagep->hasGLTexture() && imagep->getDiscardLevel() < imagep->getDesiredDiscardLevel() &&
+ (imagep->getDesiredDiscardLevel() <= MAX_DISCARD_LEVEL))
+ {
+ // NOTE: this may happen if the desired discard reduces while a decode is in progress and does not
+ // necessarily indicate a problem, but if log occurrences excede that of dsiplay_stats: FPS,
+ // something has probably gone wrong.
+ LL_WARNS_ONCE("Texture") << "Texture will be downscaled immediately after loading." << LL_ENDL;
+ imagep->scaleDown();
+ }
if (create_timer.getElapsedTimeF32() > max_time)
{
break;
}
}
- mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
+
+ if (!mDownScaleQueue.empty() && gPipeline.mDownResMap.isComplete())
+ {
+ LLGLDisable blend(GL_BLEND);
+ gGL.setColorMask(true, true);
+
+ // just in case we downres textures, bind downresmap and copy program
+ gPipeline.mDownResMap.bindTarget();
+ gCopyProgram.bind();
+ gPipeline.mScreenTriangleVB->setBuffer();
+
+ // give time to downscaling first -- if mDownScaleQueue is not empty, we're running out of memory and need
+ // to free up memory by discarding off screen textures quickly
+
+ // do at least 5 and make sure we don't get too far behind even if it violates
+ // the time limit. If we don't downscale quickly the viewer will hit swap and may
+ // freeze.
+ S32 min_count = (S32)mCreateTextureList.size() / 20 + 5;
+
+ create_timer.reset();
+ while (!mDownScaleQueue.empty())
+ {
+ LLViewerFetchedTexture* image = mDownScaleQueue.front();
+ llassert(image->mDownScalePending);
+
+ LLImageGL* img = image->getGLTexture();
+ if (img && img->getHasGLTexture())
+ {
+ img->scaleDown(image->getDesiredDiscardLevel());
+ }
+
+ image->mDownScalePending = false;
+ mDownScaleQueue.pop();
+
+ if (create_timer.getElapsedTimeF32() > max_time && --min_count <= 0)
+ {
+ break;
+ }
+ }
+
+ gCopyProgram.unbind();
+ gPipeline.mDownResMap.flush();
+ }
+
return create_timer.getElapsedTimeF32();
}
@@ -1133,18 +1213,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);
- }
imagep->processTextureStats();
- imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;
- addImageToList(imagep);
return ;
}
@@ -1152,18 +1226,34 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
typedef std::vector<LLPointer<LLViewerFetchedTexture> > entries_list_t;
entries_list_t entries;
// 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);
+ if (LLViewerTexture::sDesiredDiscardBias > 1.f
+ && LLViewerTexture::sBiasTexturesUpdated < (U32)mUUIDMap.size())
+ {
+ // We are over memory target. Bias affects discard rates, so update
+ // existing textures agresively to free memory faster.
+ update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias);
+
+ // This isn't particularly precise and can overshoot, but it doesn't need
+ // to be, just making sure it did a full circle and doesn't get stuck updating
+ // at bias = 4 with 4 times the rate permanently.
+ LLViewerTexture::sBiasTexturesUpdated += update_count;
+ }
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
@@ -1186,30 +1276,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();
}
@@ -1218,7 +1300,7 @@ void LLViewerTextureList::updateImagesUpdateStats()
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mForceResetTextureStats)
{
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1238,7 +1320,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1258,7 +1340,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
image_list.clear();
// Update fetch (decode)
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1285,7 +1367,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
}
}
// Update fetch again
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1365,6 +1447,15 @@ bool LLViewerTextureList::createUploadFile(const std::string& filename,
image->setLastError("Couldn't load the image to be uploaded.");
return false;
}
+
+ // calcDataSizeJ2C assumes maximum size is 2048 and for bigger images can
+ // assign discard to bring imige to needed size, but upload does the scaling
+ // as needed, so just reset discard.
+ // Assume file is full and has 'discard' 0 data.
+ // Todo: probably a better idea to have some setMaxDimentions in J2C
+ // called when loading from a local file
+ image->setDiscardLevel(0);
+
// Decompress or expand it in a raw image structure
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
if (!image->decode(raw_image, 0.0f))