diff options
Diffstat (limited to 'indra/newview/llviewertexturelist.cpp')
-rw-r--r-- | indra/newview/llviewertexturelist.cpp | 259 |
1 files changed, 192 insertions, 67 deletions
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 38e35b3d58..bde676bc47 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 = @@ -371,10 +374,31 @@ void LLViewerTextureList::shutdown() mInitialized = false ; //prevent loading textures again. } +namespace +{ + +std::string tex_name_as_string(const LLViewerFetchedTexture* image) +{ + if (!image->getGLTexture()) { return std::string("N/A"); } + return std::to_string(image->getGLTexture()->getTexName()); +} + +const std::string& tex_label_as_string(const LLViewerFetchedTexture* image, std::string& label) +{ + bool error; + image->getGLObjectLabel(label, error); + if (error) { label.assign("N/A"); } + return label; +} + +}; + void LLViewerTextureList::dump() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - LL_INFOS() << "LLViewerTextureList::dump()" << LL_ENDL; + LL_INFOS() << __FUNCTION__ << "()" << LL_ENDL; + + std::string label; for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) { LLViewerFetchedTexture* image = *it; @@ -385,6 +409,9 @@ void LLViewerTextureList::dump() << " discard " << image->getDiscardLevel() << " desired " << image->getDesiredDiscardLevel() << " http://asset.siva.lindenlab.com/" << image->getID() << ".texture" + << " faces " << image->getTotalNumFaces() + << " texname " << tex_name_as_string(image) + << " label \"" << tex_label_as_string(image, label) << "\"" << LL_ENDL; } } @@ -413,6 +440,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 ; @@ -428,7 +456,12 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& std::string url = "file://" + full_path; - return getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + LLViewerFetchedTexture* tex = getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + if (gDebugTextureLabelLocalFilesSession) + { + gTextureList.mNameTextureList.push_back(LLViewerTextureList::NameElement(tex, filename)); + } + return tex; } LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url, @@ -850,6 +883,10 @@ void LLViewerTextureList::updateImages(F32 max_time) //handle results from decode threads updateImagesCreateTextures(remaining_time); + // Label all images (if enabled) + updateImagesNameTextures(); + labelAll(); + bool didone = false; for (image_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) @@ -895,79 +932,90 @@ 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> 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); + 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]; + F32 bias = (F32) llroundf(powf(4, LLViewerTexture::sDesiredDiscardBias - 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; + static LLCachedControl<F32> bias_unimportant_threshold(gSavedSettings, "TextureBiasUnimportantFactor", 0.25f); + + 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; + } + + 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 (LLViewerTexture::sDesiredDiscardBias > 1.5f || - (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) - { - imagep->mMaxVirtualSize = 0.f; + 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 - imagep->addTextureStats(max_vsize); + 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", @@ -1108,6 +1156,75 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) return create_timer.getElapsedTimeF32(); } +void LLViewerTextureList::updateImagesNameTextures() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + if (gGLManager.mIsDisabled) { return; } + static LLCachedControl<bool> debug_texture_label(gSavedSettings, "RenderDebugTextureLabel", false); + if (!debug_texture_label()) { return; } + +#ifndef LL_DARWIN + static GLsizei max_length = 0; + if (max_length == 0) { glGetIntegerv(GL_MAX_LABEL_LENGTH, &max_length); } +#endif + + auto it = mNameTextureList.begin(); + while (it != mNameTextureList.end()) // For ALL textures needing names + { + LLViewerFetchedTexture* tex = it->mTex; + // Check that the texture is in the list first (otherwise it may be a dead pointer) + // A raw pointer ensures textures are cleaned up when this code isn't running. + const bool alive = mImageList.find(tex) != mImageList.end(); + + if (alive) + { + if (tex->hasGLTexture()) + { + if(tex->getTexName()) + { + tex->setGLObjectLabel(it->mPrefix, true); + it = mNameTextureList.erase(it); // Assume no rename needed + } + else + { + ++it; // Not ready + } + } + else + { + ++it; // Not ready + } + } + else + { + it = mNameTextureList.erase(it); // Remove dead pointer + } + } +} + +void LLViewerTextureList::labelAll() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + static LLCachedControl<bool> debug_texture_label(gSavedSettings, "RenderDebugTextureLabel", false); + if (!debug_texture_label()) { return; } + + static const std::string local_prefix = "lltexlocal"; + static const std::string other_prefix = "lltexother"; + + std::string label; + bool error; + for (LLViewerFetchedTexture* image : mImageList) + { + image->getGLObjectLabel(label, error); + if (!error && label.empty()) + { + const S32 category = image->getGLTexture()->getCategory(); + const std::string& new_prefix = category == LLGLTexture::LOCAL ? local_prefix : other_prefix; + image->setGLObjectLabel(new_prefix, true); + } + } +} + F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -1164,6 +1281,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 @@ -1290,6 +1412,10 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) max_time = llmax(max_time, .001f); F32 create_time = updateImagesCreateTextures(max_time); + // Label all images (if enabled) + updateImagesNameTextures(); + labelAll(); + LL_DEBUGS("ViewerImages") << "decodeAllImages() took " << timer.getElapsedTimeF32() << " seconds. " << " fetch_pending " << fetch_pending << " create_time " << create_time @@ -1313,6 +1439,11 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image, raw_image->getComponents()); LLPointer<LLImageJ2C> compressedImage = LLViewerTextureList::convertToUploadFile(scale_image, max_image_dimentions); + if (compressedImage.isNull()) + { + LL_INFOS() << "Couldn't convert to j2c, file : " << out_filename << LL_ENDL; + return false; + } if (compressedImage->getWidth() < min_image_dimentions || compressedImage->getHeight() < min_image_dimentions) { std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx", @@ -1323,12 +1454,6 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image, compressedImage->setLastError(reason); return false; } - if (compressedImage.isNull()) - { - compressedImage->setLastError("Couldn't convert the image to jpeg2000."); - LL_INFOS() << "Couldn't convert to j2c, file : " << out_filename << LL_ENDL; - return false; - } if (!compressedImage->save(out_filename)) { compressedImage->setLastError("Couldn't create the jpeg2000 image for upload."); |