diff options
| author | Dave Parks <davep@lindenlab.com> | 2024-07-03 17:42:24 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-03 17:42:24 -0500 | 
| commit | 08b933a0c67463f06f124420f16c8a3f7dc83f1f (patch) | |
| tree | 4ca6d47a6b055d332cb75646226c13e950f37ce4 /indra/newview | |
| parent | 9a38ecee8ef54b3e85a88657d7ba96c3292e350e (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.xml | 13 | ||||
| -rw-r--r-- | indra/newview/featuretable.txt | 4 | ||||
| -rw-r--r-- | indra/newview/gltf/accessor.h | 2 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/gltf/common.h | 2 | ||||
| -rw-r--r-- | indra/newview/gltfscenemanager.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 12 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolalpha.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llface.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/lltextureview.cpp | 15 | ||||
| -rw-r--r-- | indra/newview/llviewerassetstorage.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.cpp | 87 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.h | 23 | ||||
| -rw-r--r-- | indra/newview/llviewertexturelist.cpp | 173 | ||||
| -rw-r--r-- | indra/newview/llviewertexturelist.h | 13 | ||||
| -rw-r--r-- | indra/newview/llvograss.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llvotree.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 27 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 3 | 
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; | 
