summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2024-07-03 17:42:24 -0500
committerGitHub <noreply@github.com>2024-07-03 17:42:24 -0500
commit08b933a0c67463f06f124420f16c8a3f7dc83f1f (patch)
tree4ca6d47a6b055d332cb75646226c13e950f37ce4 /indra/newview
parent9a38ecee8ef54b3e85a88657d7ba96c3292e350e (diff)
#1870 Tune up for better experience on integrated intel with low memory (#1872)
* More deterministic vsize calculation. Add control for choosing downscale method. * Quick hack to make GLTF preview work again
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml13
-rw-r--r--indra/newview/featuretable.txt4
-rw-r--r--indra/newview/gltf/accessor.h2
-rw-r--r--indra/newview/gltf/asset.cpp1
-rw-r--r--indra/newview/gltf/common.h2
-rw-r--r--indra/newview/gltfscenemanager.cpp6
-rw-r--r--indra/newview/llappviewer.cpp12
-rw-r--r--indra/newview/lldrawpoolalpha.cpp4
-rw-r--r--indra/newview/llface.cpp4
-rw-r--r--indra/newview/lltextureview.cpp15
-rw-r--r--indra/newview/llviewerassetstorage.cpp1
-rw-r--r--indra/newview/llviewertexture.cpp87
-rw-r--r--indra/newview/llviewertexture.h23
-rw-r--r--indra/newview/llviewertexturelist.cpp173
-rw-r--r--indra/newview/llviewertexturelist.h13
-rw-r--r--indra/newview/llvograss.cpp3
-rw-r--r--indra/newview/llvotree.cpp8
-rw-r--r--indra/newview/llvovolume.cpp27
-rw-r--r--indra/newview/pipeline.cpp6
-rw-r--r--indra/newview/pipeline.h3
20 files changed, 279 insertions, 128 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 09909aa9c4..7f645792a6 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7732,7 +7732,7 @@
<key>Comment</key>
<string>Minimum of available physical memory in MB before textures get scaled down</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
@@ -7771,6 +7771,17 @@
<key>Value</key>
<integer>2048</integer>
</map>
+ <key>RenderDownScaleMethod</key>
+ <map>
+ <key>Comment</key>
+ <string>Method to use to downscale images. 0 - FBO, 1 - PBO</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RenderDebugTextureBind</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 03849a0326..af1587bd07 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 60
+version 61
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -76,6 +76,7 @@ RenderGLMultiThreadedMedia 1 1
RenderReflectionProbeResolution 1 128
RenderScreenSpaceReflections 1 1
RenderMirrors 1 1
+RenderDownScaleMethod 1 1
//
@@ -366,6 +367,7 @@ RenderAnisotropic 1 0
RenderFSAASamples 1 0
RenderGLContextCoreProfile 1 0
RenderGLMultiThreadedMedia 1 0
+RenderDownScaleMethod 1 0
list AMD
RenderGLMultiThreadedTextures 1 1
diff --git a/indra/newview/gltf/accessor.h b/indra/newview/gltf/accessor.h
index ec68c5f624..85ea0f2967 100644
--- a/indra/newview/gltf/accessor.h
+++ b/indra/newview/gltf/accessor.h
@@ -36,8 +36,6 @@ namespace LL
{
namespace GLTF
{
- constexpr S32 INVALID_INDEX = -1;
-
class Buffer
{
public:
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp
index a454e68a92..e07befef3b 100644
--- a/indra/newview/gltf/asset.cpp
+++ b/indra/newview/gltf/asset.cpp
@@ -476,6 +476,7 @@ void Asset::update()
{ // HACK - force texture to be loaded full rez
// TODO: calculate actual vsize
image.mTexture->addTextureStats(2048.f * 2048.f);
+ image.mTexture->setBoostLevel(LLViewerTexture::BOOST_HIGH);
}
}
}
diff --git a/indra/newview/gltf/common.h b/indra/newview/gltf/common.h
index b9698d4017..742daff715 100644
--- a/indra/newview/gltf/common.h
+++ b/indra/newview/gltf/common.h
@@ -43,6 +43,8 @@ namespace LL
{
namespace GLTF
{
+ constexpr S32 INVALID_INDEX = -1;
+
using Value = boost::json::value;
using mat4 = glm::mat4;
diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp
index b161ec8492..58179f9dc3 100644
--- a/indra/newview/gltfscenemanager.cpp
+++ b/indra/newview/gltfscenemanager.cpp
@@ -345,6 +345,12 @@ void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
llassert(obj->getVolume()->getParams().getSculptID() == gltf_id);
llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF);
+ if (obj->mGLTFAsset)
+ { // object already has a GLTF asset, don't reload it
+ llassert(std::find(mObjects.begin(), mObjects.end(), obj) != mObjects.end());
+ return;
+ }
+
obj->ref();
gAssetStorage->getAssetData(gltf_id, LLAssetType::AT_GLTF, onGLTFLoadComplete, obj);
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 51099a480d..ac689f7319 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2210,10 +2210,10 @@ bool LLAppViewer::initThreads()
cores = llmin(cores, (S32) max_cores);
}
- // The only configurable thread count right now is ImageDecode
- // The viewer typically starts around 8 threads not including image decode,
- // so try to leave at least one core free
- S32 image_decode_count = llclamp(cores - 9, 1, 8);
+ // always use at least 2 threads for image decoding to prevent
+ // a single texture blocking all other textures from decoding
+ S32 image_decode_count = llclamp(cores - 6, 2, 16);
+
threadCounts["ImageDecode"] = image_decode_count;
gSavedSettings.setLLSD("ThreadPoolSizes", threadCounts);
@@ -4609,6 +4609,10 @@ void LLAppViewer::idle()
LLGLTFMaterialList::flushUpdates();
+ static LLCachedControl<U32> downscale_method(gSavedSettings, "RenderDownScaleMethod");
+ gGLManager.mDownScaleMethod = downscale_method;
+ LLImageGL::updateClass();
+
// Service the WorkQueue we use for replies from worker threads.
// Use function statics for the timeslice setting so we only have to fetch
// and convert MainWorkTime once.
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 34da5b29d4..2d702ecf32 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -81,10 +81,6 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
void LLDrawPoolAlpha::prerender()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
-
- // TODO: is this even necessay? These are probably set to never discard
- LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f);
- LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f);
}
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 0e8e64af69..777ea611b0 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -169,6 +169,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mImportanceToCamera = 0.f ;
mBoundingSphereRadius = 0.0f ;
+ mTexExtents[0].set(0, 0);
+ mTexExtents[1].set(1, 1);
mHasMedia = false ;
mIsMediaAllowed = true;
}
@@ -2047,10 +2049,12 @@ void LLFace::resetVirtualSize()
F32 LLFace::getTextureVirtualSize()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
F32 radius;
F32 cos_angle_to_view_dir;
bool in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
+
if (mPixelArea < F_ALMOST_ZERO || !in_frustum)
{
setVirtualSize(0.f) ;
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 9d7319d5b8..9e86548c2d 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -530,6 +530,9 @@ void LLGLTexMemBar::draw()
F64 raw_image_bytes_MB = raw_image_bytes / (1024.0 * 1024.0);
F64 saved_raw_image_bytes_MB = saved_raw_image_bytes / (1024.0 * 1024.0);
F64 aux_raw_image_bytes_MB = aux_raw_image_bytes / (1024.0 * 1024.0);
+ F64 texture_bytes_alloc = LLImageGL::getTextureBytesAllocated() / 1024.0 / 1024.0 * 1.3333f; // add 33% for mipmaps
+ F64 vertex_bytes_alloc = LLVertexBuffer::getBytesAllocated() / 1024.0 / 1024.0;
+ F64 render_bytes_alloc = LLRenderTarget::sBytesAllocated / 1024.0 / 1024.0;
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
@@ -559,7 +562,7 @@ void LLGLTexMemBar::draw()
// draw a background above first line.... no idea where the rest of the background comes from for the below text
gGL.color4f(0.f, 0.f, 0.f, 0.25f);
- gl_rect_2d(-10, getRect().getHeight() + line_height + 1, getRect().getWidth()+2, getRect().getHeight()+2);
+ gl_rect_2d(-10, getRect().getHeight() + line_height*2 + 1, getRect().getWidth()+2, getRect().getHeight()+2);
text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
(S32)LLViewerTexture::sFreeVRAMMegabytes,
@@ -568,12 +571,20 @@ void LLGLTexMemBar::draw()
discard_bias,
cache_usage,
cache_max_usage);
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*7,
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*8,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
text = llformat("Images: %d Raw: %d (%.2f MB) Saved: %d (%.2f MB) Aux: %d (%.2f MB)", image_count, raw_image_count, raw_image_bytes_MB,
saved_raw_image_count, saved_raw_image_bytes_MB,
aux_raw_image_count, aux_raw_image_bytes_MB);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 7,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ text = llformat("Textures: %.2f MB Vertex: %.2f MB Render: %.2f MB Total: %.2f MB",
+ texture_bytes_alloc,
+ vertex_bytes_alloc,
+ render_bytes_alloc,
+ texture_bytes_alloc+vertex_bytes_alloc+render_bytes_alloc);
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 6,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 26707f5d9a..5ab9f76e47 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -376,6 +376,7 @@ void LLViewerAssetStorage::queueRequestHttp(
bool duplicate,
bool is_priority)
{
+ LL_PROFILE_ZONE_SCOPED;
LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL;
bool with_http = true;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index b2ed86707c..99c917ca6f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -89,7 +89,7 @@ S32 LLViewerTexture::sRawCount = 0;
S32 LLViewerTexture::sAuxCount = 0;
LLFrameTimer LLViewerTexture::sEvaluationTimer;
F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
-F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
+
S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64;
const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez;
@@ -513,15 +513,18 @@ void LLViewerTexture::updateClass()
F32 target = llmax(budget - 512.f, MIN_VRAM_BUDGET);
sFreeVRAMMegabytes = target - used;
- F32 over_pct = llmax((used-target) / target, 0.f);
+ F32 over_pct = (used - target) / target;
+
+ bool is_low = over_pct > 0.f;
if (isSystemMemoryLow())
{
+ is_low = true;
// System RAM is low -> ramp up discard bias over time to free memory
if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME)
{
static LLCachedControl<F32> low_mem_min_discard_increment(gSavedSettings, "RenderLowMemMinDiscardIncrement", .1f);
- sDesiredDiscardBias += llmax(low_mem_min_discard_increment, over_pct);
+ sDesiredDiscardBias += (F32) low_mem_min_discard_increment * (F32) gFrameIntervalSeconds;
sEvaluationTimer.reset();
}
}
@@ -529,12 +532,28 @@ void LLViewerTexture::updateClass()
{
sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
- if (sDesiredDiscardBias > 1.f)
+ if (sDesiredDiscardBias > 1.f && over_pct < 0.f)
{
sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01;
}
}
+ static bool was_low = false;
+ if (is_low && !was_low)
+ {
+ LL_WARNS() << "Low system memory detected, emergency downrezzing off screen textures" << LL_ENDL;
+ sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.5f);
+
+ for (auto image : gTextureList)
+ {
+ gTextureList.updateImageDecodePriority(image);
+ }
+ }
+
+ was_low = is_low;
+
+ sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 3.f);
+
LLViewerTexture::sFreezeImageUpdates = false;
}
@@ -615,16 +634,15 @@ void LLViewerTexture::init(bool firstinit)
mParcelMedia = NULL;
memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS);
- mFaceList[LLRender::DIFFUSE_MAP].clear();
- mFaceList[LLRender::NORMAL_MAP].clear();
- mFaceList[LLRender::SPECULAR_MAP].clear();
- mNumFaces[LLRender::DIFFUSE_MAP] =
- mNumFaces[LLRender::NORMAL_MAP] =
- mNumFaces[LLRender::SPECULAR_MAP] = 0;
-
mVolumeList[LLRender::LIGHT_TEX].clear();
mVolumeList[LLRender::SCULPT_TEX].clear();
+ for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; i++)
+ {
+ mNumFaces[i] = 0;
+ mFaceList[i].clear();
+ }
+
mMainQueue = LL::WorkQueue::getInstance("mainloop");
mImageQueue = LL::WorkQueue::getInstance("LLImageGL");
}
@@ -1608,7 +1626,11 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
}
else
{
- gTextureList.mCreateTextureList.insert(this);
+ if (!mCreatePending)
+ {
+ mCreatePending = true;
+ gTextureList.mCreateTextureList.push(this);
+ }
}
}
}
@@ -1632,13 +1654,12 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
void LLViewerFetchedTexture::setDebugText(const std::string& text)
{
- for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
+ for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
- llassert(mNumFaces[ch] <= mFaceList[ch].size());
-
- for (U32 i = 0; i < mNumFaces[ch]; i++)
+ for (S32 fi = 0; fi < getNumFaces(i); ++fi)
{
- LLFace* facep = mFaceList[ch][i];
+ LLFace* facep = (*(getFaceList(i)))[fi];
+
if (facep)
{
LLDrawable* drawable = facep->getDrawable();
@@ -1651,10 +1672,15 @@ void LLViewerFetchedTexture::setDebugText(const std::string& text)
}
}
+extern bool gCubeSnapshot;
+
//virtual
void LLViewerFetchedTexture::processTextureStats()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ llassert(!gCubeSnapshot); // should only be called when the main camera is active
+ llassert(!LLPipeline::sShadowRender);
+
if(mFullyLoaded)
{
if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
@@ -2859,6 +2885,8 @@ void LLViewerLODTexture::processTextureStats()
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
updateVirtualSize();
+ bool did_downscale = false;
+
static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false);
{ // restrict texture resolution to download based on RenderMaxTextureResolution
@@ -2916,10 +2944,7 @@ void LLViewerLODTexture::processTextureStats()
mDiscardVirtualSize = mMaxVirtualSize;
mCalculatedDiscardLevel = discard_level;
}
- if (mBoostLevel < LLGLTexture::BOOST_SCULPTED)
- {
- discard_level *= sDesiredDiscardScale; // scale (default 1.1f)
- }
+
discard_level = floorf(discard_level);
F32 min_discard = 0.f;
@@ -2945,10 +2970,9 @@ void LLViewerLODTexture::processTextureStats()
//
S32 current_discard = getDiscardLevel();
- if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED &&
- current_discard >= 0)
+ if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED)
{
- if (current_discard < (mDesiredDiscardLevel-1) && !mForceToSaveRawImage)
+ if (current_discard < mDesiredDiscardLevel && !mForceToSaveRawImage)
{ // should scale down
scaleDown();
}
@@ -2968,9 +2992,6 @@ void LLViewerLODTexture::processTextureStats()
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel);
}
- // decay max virtual size over time
- mMaxVirtualSize *= 0.8f;
-
// selection manager will immediately reset BOOST_SELECTED but never unsets it
// unset it immediately after we consume it
if (getBoostLevel() == BOOST_SELECTED)
@@ -2979,14 +3000,22 @@ void LLViewerLODTexture::processTextureStats()
}
}
+extern LLGLSLShader gCopyProgram;
+
bool LLViewerLODTexture::scaleDown()
{
- if (mGLTexturep.isNull())
+ if (mGLTexturep.isNull() || !mGLTexturep->getHasGLTexture())
{
return false;
}
- return mGLTexturep->scaleDown(mDesiredDiscardLevel);
+ if (!mDownScalePending)
+ {
+ mDownScalePending = true;
+ gTextureList.mDownScaleQueue.push(this);
+ }
+
+ return true;
}
//----------------------------------------------------------------------------------------------
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index b1e0494a30..5b2e3aaab7 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -37,6 +37,7 @@
#include "llmetricperformancetester.h"
#include "httpcommon.h"
#include "workqueue.h"
+#include "gltf/common.h"
#include <map>
#include <list>
@@ -102,7 +103,6 @@ public:
DYNAMIC_TEXTURE,
FETCHED_TEXTURE,
LOD_TEXTURE,
- ATLAS_TEXTURE,
INVALID_TEXTURE_TYPE
};
@@ -173,6 +173,15 @@ public:
LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
/*virtual*/ void updateBindStatsForTester() ;
+
+ struct MaterialEntry
+ {
+ S32 mIndex = LL::GLTF::INVALID_INDEX;
+ std::shared_ptr<LL::GLTF::Asset> mAsset;
+ };
+ typedef std::vector<MaterialEntry> material_list_t;
+ material_list_t mMaterialList; // reverse pointer pointing to LL::GLTF::Materials using this image as texture
+
protected:
void cleanup() ;
void init(bool firstinit) ;
@@ -214,7 +223,6 @@ public:
static S32 sAuxCount;
static LLFrameTimer sEvaluationTimer;
static F32 sDesiredDiscardBias;
- static F32 sDesiredDiscardScale;
static S32 sMaxSculptRez ;
static U32 sMinLargeImageSize ;
static U32 sMaxSmallImageSize ;
@@ -414,6 +422,9 @@ public:
/*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline.
+ bool mCreatePending = false; // if true, this is in gTextureList.mCreateTextureList
+ mutable bool mDownScalePending = false; // if true, this is in gTextureList.mDownScaleQueue
+
protected:
S32 getCurrentDiscardLevelForFetching() ;
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
@@ -424,11 +435,6 @@ private:
void saveRawImage() ;
- //for atlas
- void resetFaceAtlas() ;
- void invalidateAtlas(bool rebuild_geom) ;
- bool insertToAtlas() ;
-
private:
bool mFullyLoaded;
bool mInDebug;
@@ -539,9 +545,10 @@ public:
/*virtual*/ void processTextureStats();
bool isUpdateFrozen() ;
+ bool scaleDown();
+
private:
void init(bool firstinit) ;
- bool scaleDown() ;
private:
F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 2f685474e1..c436566297 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -70,6 +70,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;
@@ -352,8 +354,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();
@@ -897,14 +902,6 @@ void LLViewerTextureList::clearFetchingRequests()
}
}
-static void touch_texture(LLViewerFetchedTexture* tex, F32 vsize)
-{
- if (tex)
- {
- tex->addTextureStats(vsize);
- }
-}
-
extern bool gCubeSnapshot;
void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imagep)
@@ -921,58 +918,67 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
static LLCachedControl<F32> texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.04f);
static LLCachedControl<F32> texture_scale_max(gSavedSettings, "TextureScaleMaxAreaFactor", 25.f);
+ if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE)
+ { // 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
+ imagep->mMaxVirtualSize = 0.f;
+ }
+
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE
+ for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
- for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
+ for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
{
- for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
+ LLFace* face = (*(imagep->getFaceList(i)))[fi];
+
+ if (face && face->getViewerObject())
{
- LLFace* face = (*(imagep->getFaceList(i)))[fi];
+ F32 radius;
+ F32 cos_angle_to_view_dir;
+ bool in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
+ static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f);
+ F32 vsize = face->getPixelArea();
+
+ // 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
+ const LLTextureEntry* te = face->getTextureEntry();
+ 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;
+ }
- if (face && face->getViewerObject() && face->getTextureEntry())
+ if (apply_bias)
{
- F32 radius;
- F32 cos_angle_to_view_dir;
- BOOL in_frustum = face->calcPixelArea(cos_angle_to_view_dir, radius);
- static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f);
- F32 vsize = face->getPixelArea();
-
- // 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
- const LLTextureEntry* te = face->getTextureEntry();
- 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 (!in_frustum || !face->getDrawable()->isVisible() || face->getImportanceToCamera() < bias_unimportant_threshold)
- { // further reduce by discard bias when off screen or occluded
- vsize /= LLViewerTexture::sDesiredDiscardBias;
- }
- // 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)
- {
- touch_texture(mat->mBaseColorTexture, vsize);
- touch_texture(mat->mNormalTexture, vsize);
- touch_texture(mat->mMetallicRoughnessTexture, vsize);
- touch_texture(mat->mEmissiveTexture, vsize);
- }
- else
- {
- imagep->addTextureStats(vsize);
- }
+ F32 bias = powf(4, LLViewerTexture::sDesiredDiscardBias - 1.f);
+ bias = llround(bias);
+ vsize /= bias;
}
+
+ imagep->addTextureStats(vsize);
}
}
}
+ // 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 lazy_flush_timeout = 30.f; // stop decoding
@@ -1066,22 +1072,65 @@ 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();)
+
+ if (!mDownScaleQueue.empty() && gPipeline.mDownResMap.isComplete())
{
- image_list_t::iterator curiter = iter++;
- enditer = iter;
- LLViewerFetchedTexture *imagep = *curiter;
+ // 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;
+
+ 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();
+ }
+
+ // 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)
+ if (create_timer.getElapsedTimeF32() > max_time && --min_count <= 0)
{
break;
}
}
- mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
return create_timer.getElapsedTimeF32();
}
@@ -1124,7 +1173,10 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
removeImageFromList(imagep);
}
- imagep->processTextureStats();
+ if (!gCubeSnapshot)
+ { // never call processTextureStats in a cube snapshot
+ imagep->processTextureStats();
+ }
imagep->sMaxVirtualSize = LLViewerFetchedTexture::sMaxVirtualSize;
addImageToList(imagep);
@@ -1134,6 +1186,7 @@ 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;
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 2779ad9f91..813fda1647 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -144,12 +144,13 @@ public:
void clearFetchingRequests();
void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);
-private:
// do some book keeping on the specified texture
// - updates decode priority
// - updates desired discard level
// - cleans up textures that haven't been referenced in awhile
void updateImageDecodePriority(LLViewerFetchedTexture* imagep);
+
+private:
F32 updateImagesCreateTextures(F32 max_time);
F32 updateImagesFetchTextures(F32 max_time);
void updateImagesUpdateStats();
@@ -211,8 +212,14 @@ private:
public:
typedef std::unordered_set<LLPointer<LLViewerFetchedTexture> > image_list_t;
- image_list_t mLoadingStreamList;
- image_list_t mCreateTextureList;
+ typedef std::queue<LLPointer<LLViewerFetchedTexture> > image_queue_t;
+
+ // images that have been loaded but are waiting to be uploaded to GL
+ image_queue_t mCreateTextureList;
+
+ // images that must be downscaled quickly so we don't run out of memory
+ image_queue_t mDownScaleQueue;
+
image_list_t mCallbackList;
image_list_t mFastCacheList;
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index e04bdbf1d9..6903af2619 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -451,6 +451,9 @@ void LLVOGrass::plantBlades()
face->setVertexBuffer(NULL);
face->setTEOffset(0);
face->mCenterLocal = mPosition + mRegionp->getOriginAgent();
+ const LLVector4a* ext = mDrawable->getSpatialExtents();
+ face->mExtents[0] = ext[0];
+ face->mExtents[1] = ext[1];
}
mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index a981c60ef2..d982592ee7 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -461,9 +461,7 @@ void LLVOTree::updateTextures()
{
setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea)));
}
- mTreeImagep->addTextureStats(mPixelArea);
}
-
}
@@ -479,7 +477,7 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
// Just a placeholder for an actual object...
LLFace *facep = mDrawable->addFace(poolp, mTreeImagep);
facep->setSize(1, 3);
-
+ facep->setTexture(LLRender::DIFFUSE_MAP, mTreeImagep);
updateRadius();
return mDrawable;
@@ -1169,6 +1167,10 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
LLVector4a pos;
pos.load3(center.mV);
mDrawable->setPositionGroup(pos);
+
+ LLFace* facep = mDrawable->getFace(0);
+ facep->mExtents[0] = newMin;
+ facep->mExtents[1] = newMax;
}
bool LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp,
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 7ca3fbd1ad..45713071bb 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5745,18 +5745,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
continue;
}
-#if 0
-#if LL_RELEASE_WITH_DEBUG_INFO
- const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" );
- const LLUUID obj_id( vobj->getID() );
- bool is_pbr = (obj_id == pbr_id);
-#else
- bool is_pbr = false;
-#endif
-#else
- LLGLTFMaterial *gltf_mat = facep->getTextureEntry()->getGLTFRenderMaterial();
+
+ LLFetchedGLTFMaterial *gltf_mat = (LLFetchedGLTFMaterial*) facep->getTextureEntry()->getGLTFRenderMaterial();
bool is_pbr = gltf_mat != nullptr;
-#endif
+
+ if (is_pbr)
+ {
+ // tell texture streaming system to ignore blinn-phong textures
+ facep->setTexture(LLRender::DIFFUSE_MAP, nullptr);
+ facep->setTexture(LLRender::NORMAL_MAP, nullptr);
+ facep->setTexture(LLRender::SPECULAR_MAP, nullptr);
+
+ // let texture streaming system know about PBR textures
+ facep->setTexture(LLRender::BASECOLOR_MAP, gltf_mat->mBaseColorTexture);
+ facep->setTexture(LLRender::GLTF_NORMAL_MAP, gltf_mat->mNormalTexture);
+ facep->setTexture(LLRender::METALLIC_ROUGHNESS_MAP, gltf_mat->mMetallicRoughnessTexture);
+ facep->setTexture(LLRender::EMISSIVE_MAP, gltf_mat->mEmissiveTexture);
+ }
//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
// batch, it will recover its vertex buffer reference from the spatial group
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index b9b1264b16..f83774c39e 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -865,6 +865,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA;
mPostMap.allocate(resX, resY, post_color_fmt);
+ // used to scale down textures
+ // See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown
+ mDownResMap.allocate(4, 4, GL_RGBA);
+
//HACK make screenbuffer allocations start failing after 30 seconds
if (gSavedSettings.getBOOL("SimulateFBOFailure"))
{
@@ -1111,6 +1115,8 @@ void LLPipeline::releaseGLBuffers()
mPostMap.release();
+ mDownResMap.release();
+
for (U32 i = 0; i < 3; i++)
{
mGlow[i].release();
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 1d2033b4f0..6c79d20149 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -725,6 +725,9 @@ public:
// tonemapped and gamma corrected render ready for post
LLRenderTarget mPostMap;
+ // downres scratch space for GPU downscaling of textures
+ LLRenderTarget mDownResMap;
+
LLCullResult mSky;
LLCullResult mReflectedObjects;
LLCullResult mRefractedObjects;