diff options
Diffstat (limited to 'indra/newview/llviewertexturelist.cpp')
-rw-r--r-- | indra/newview/llviewertexturelist.cpp | 333 |
1 files changed, 164 insertions, 169 deletions
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index c812504f9b..38e35b3d58 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; @@ -195,13 +197,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() @@ -306,7 +301,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 +357,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 +375,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 +389,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 @@ -736,6 +728,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 +765,6 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) << LL_ENDL; } } - - image->setInImageList(false) ; } void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListType tex_type) @@ -819,15 +810,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; @@ -844,7 +826,7 @@ void LLViewerTextureList::updateImages(F32 max_time) } 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 +850,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 +881,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 +889,126 @@ 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); - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE + + F32 max_vsize = 0.f; + bool on_screen = false; + + 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; + 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; + } - if (face && face->getViewerObject() && face->getTextureEntry()) + if (apply_bias) { - 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; - 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; - } - // 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 = (F32) llround(bias); + vsize /= bias; } + + max_vsize = llmax(max_vsize, vsize); } } } - //imagep->setDebugText(llformat("%.3f - %d", sqrtf(imagep->getMaxVirtualSize()), imagep->getBoostLevel())); + 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 - 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 + if (LLViewerTexture::sDesiredDiscardBias > 1.5f || + (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + { + 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(); + } + + 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; // 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 +1021,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 +1035,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 +1046,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(); } @@ -1133,18 +1138,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 +1151,22 @@ 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); 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 +1189,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 +1213,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 +1233,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 +1253,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 +1280,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++; |