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.cpp203
1 files changed, 126 insertions, 77 deletions
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 38e35b3d58..c2eb8ddd25 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -123,6 +123,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 =
@@ -413,6 +416,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 ;
@@ -895,79 +899,100 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
{
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);
+ if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures
+ {
+ static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f);
+ static LLCachedControl<F32> texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f);
+ F32 max_vsize = 0.f;
+ bool on_screen = false;
- F32 max_vsize = 0.f;
- bool on_screen = false;
+ U32 face_count = 0;
- 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];
+ // get adjusted bias based on image resolution
+ F32 max_discard = F32(imagep->getMaxDiscardLevel());
+ 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));
- if (face && face->getViewerObject())
+ 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)
{
- F32 radius;
- F32 cos_angle_to_view_dir;
- static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f);
- F32 vsize = face->getPixelArea();
- bool in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
-
- on_screen = in_frustum;
-
- // 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
- //
- // Maximum usage examples: huge chunk of terrain repeats texture
- 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());
- vsize /= min_scale;
-
- // if bias is > 2, apply to on-screen textures as well
- bool apply_bias = LLViewerTexture::sDesiredDiscardBias > 2.f;
-
- // apply bias to off screen objects or objects that are small on screen all the time
- if (!in_frustum || !face->getDrawable()->isVisible() || face->getImportanceToCamera() < bias_unimportant_threshold)
- { // further reduce by discard bias when off screen or occluded
- apply_bias = true;
- }
+ LLFace* face = (*(imagep->getFaceList(i)))[fi];
- if (apply_bias)
+ if (face && face->getViewerObject())
{
- F32 bias = powf(4, LLViewerTexture::sDesiredDiscardBias - 1.f);
- bias = (F32) llround(bias);
- vsize /= bias;
+ ++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
+ //
+ // Maximum usage examples: huge chunk of terrain repeats texture
+ // 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());
+ vsize /= min_scale;
+
+ // apply bias to offscreen faces all the time, but only to onscreen faces when bias is large
+ if (!face->mInFrustum || LLViewerTexture::sDesiredDiscardBias > 2.f)
+ {
+ vsize /= bias;
+ }
+
+ // boost resolution of textures that are important to the camera
+ if (face->mInFrustum)
+ {
+ static LLCachedControl<F32> texture_camera_boost(gSavedSettings, "TextureCameraBoost", 8.f);
+ vsize *= llmax(face->mImportanceToCamera*texture_camera_boost, 1.f);
+ }
+
+ max_vsize = llmax(max_vsize, vsize);
}
-
- max_vsize = llmax(max_vsize, vsize);
}
}
- }
- 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 (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);
+ }
+
+ 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 > 1.5f ||
- (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f))
- {
- imagep->mMaxVirtualSize = 0.f;
+ (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f))
+ {
+ imagep->mMaxVirtualSize = 0.f;
+ }
}
- }
-
- imagep->addTextureStats(max_vsize);
+ imagep->addTextureStats(max_vsize);
+ }
#if 0
imagep->setDebugText(llformat("%d/%d - %d/%d -- %d/%d",
@@ -1047,8 +1072,45 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
LLTimer create_timer;
+ while (!mCreateTextureList.empty())
+ {
+ 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())
+ {
+ // 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;
+ }
+ }
+
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();
@@ -1062,6 +1124,7 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
// freeze.
S32 min_count = (S32)mCreateTextureList.size() / 20 + 5;
+ create_timer.reset();
while (!mDownScaleQueue.empty())
{
LLViewerFetchedTexture* image = mDownScaleQueue.front();
@@ -1086,25 +1149,6 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
gPipeline.mDownResMap.flush();
}
- // do at least 5 and make sure we don't get too far behind even if it violates
- // the time limit. Textures pending creation have a copy of their texture data
- // in system memory, so we don't want to let them pile up.
- S32 min_count = (S32) mCreateTextureList.size() / 20 + 5;
-
- while (!mCreateTextureList.empty())
- {
- LLViewerFetchedTexture *imagep = mCreateTextureList.front();
- llassert(imagep->mCreatePending);
- imagep->createTexture();
- imagep->postCreateTexture();
- imagep->mCreatePending = false;
- mCreateTextureList.pop();
-
- if (create_timer.getElapsedTimeF32() > max_time && --min_count <= 0)
- {
- break;
- }
- }
return create_timer.getElapsedTimeF32();
}
@@ -1164,6 +1208,11 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
//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)
+ {
+ // we are over memory target, update more agresively
+ update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias);
+ }
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