void LLViewerImageList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame { const size_t max_update_count = llmin((S32) (1024*gFrameIntervalSeconds) + 1, 32); //target 1024 textures per second S32 update_counter = llmin(max_update_count, mUUIDMap.size()/10); uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID); while(update_counter > 0 && !mUUIDMap.empty()) { if (iter == mUUIDMap.end()) { iter = mUUIDMap.begin(); } mLastUpdateUUID = iter->first; LLPointer<LLViewerImage> imagep = iter->second; ++iter; // safe to incrament now // // Flush formatted images using a lazy flush // const F32 LAZY_FLUSH_TIMEOUT = 30.f; S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference if (imagep->hasCallbacks()) { min_refs++; // Add an extra reference if we're on the loaded callback list } S32 num_refs = imagep->getNumRefs(); if (num_refs == min_refs) { if (imagep->mLastReferencedTimer.getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) { // Remove the unused image from the image list deleteImage(imagep); imagep = NULL; // should destroy the image continue; } } else { imagep->mLastReferencedTimer.reset(); } imagep->processTextureStats(); F32 old_priority = imagep->getDecodePriority(); F32 decode_priority = imagep->calcDecodePriority(); // Ignore < 20% difference if ((decode_priority < old_priority * .8f || decode_priority > old_priority * 1.25f)) { removeImageFromList(imagep); imagep->setDecodePriority(decode_priority); addImageToList(imagep); } update_counter--; } } }
void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep) { if(!imagep) { return ; } if(imagep->isInImageList()) { removeImageFromList(imagep); } imagep->processTextureStats(); F32 decode_priority = LLViewerFetchedTexture::maxDecodePriority() ; imagep->setDecodePriority(decode_priority); addImageToList(imagep); return ; }
void LLViewerImageList::addImage(LLViewerImage *new_image) { if (!new_image) { llwarning("No image to add to image list", 0); return; } LLUUID image_id = new_image->getID(); LLViewerImage *image = hasImage(image_id); if (image) { llwarns << "Image with ID " << image_id << " already in list" << llendl; } sNumImages++; addImageToList(new_image); mUUIDMap[image_id] = new_image; }
void LLViewerTextureList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame { const size_t max_update_count = llmin((S32) (1024*gFrameIntervalSeconds) + 1, 32); //target 1024 textures per second S32 update_counter = llmin(max_update_count, mUUIDMap.size()/10); uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID); while(update_counter > 0 && !mUUIDMap.empty()) { if (iter == mUUIDMap.end()) { iter = mUUIDMap.begin(); } mLastUpdateUUID = iter->first; LLPointer<LLViewerFetchedTexture> imagep = iter->second; ++iter; // safe to incrament now // // Flush formatted images using a lazy flush // const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding const F32 MAX_INACTIVE_TIME = 50.f; // actually delete S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference if (imagep->hasCallbacks()) { min_refs++; // Add an extra reference if we're on the loaded callback list } S32 num_refs = imagep->getNumRefs(); if (num_refs == min_refs) { if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) { // Remove the unused image from the image list deleteImage(imagep); imagep = NULL; // should destroy the image } continue; } else { if(imagep->hasSavedRawImage()) { if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME) { imagep->destroySavedRawImage() ; } } if(imagep->isDeleted()) { continue ; } else if(imagep->isDeletionCandidate()) { imagep->destroyTexture() ; continue ; } else if(imagep->isInactive()) { if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) { imagep->setDeletionCandidate() ; } continue ; } else { imagep->getLastReferencedTimer()->reset(); //reset texture state. imagep->setInactive() ; } } imagep->processTextureStats(); F32 old_priority = imagep->getDecodePriority(); F32 old_priority_test = llmax(old_priority, 0.0f); F32 decode_priority = imagep->calcDecodePriority(); F32 decode_priority_test = llmax(decode_priority, 0.0f); // Ignore < 20% difference if ((decode_priority_test < old_priority_test * .8f) || (decode_priority_test > old_priority_test * 1.25f)) { removeImageFromList(imagep); imagep->setDecodePriority(decode_priority); addImageToList(imagep); } update_counter--; } } }
void LLViewerTextureList::decodeAllImages(F32 max_time) { LLTimer timer; llassert_always(sRenderThreadID == LLThread::currentID()); // Update texture stats and priorities std::vector<LLPointer<LLViewerFetchedTexture> > image_list; for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerFetchedTexture* imagep = *iter++; image_list.push_back(imagep); imagep->setInImageList(FALSE) ; } mImageList.clear(); for (std::vector<LLPointer<LLViewerFetchedTexture> >::iterator iter = image_list.begin(); iter != image_list.end(); ++iter) { LLViewerFetchedTexture* imagep = *iter; imagep->processTextureStats(); F32 decode_priority = imagep->calcDecodePriority(); imagep->setDecodePriority(decode_priority); addImageToList(imagep); } image_list.clear(); // Update fetch (decode) for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerFetchedTexture* imagep = *iter++; imagep->updateFetch(); } // Run threads S32 fetch_pending = 0; while (1) { LLAppViewer::instance()->getTextureCache()->update(1); // unpauses the texture cache thread LLAppViewer::instance()->getImageDecodeThread()->update(1); // unpauses the image thread fetch_pending = LLAppViewer::instance()->getTextureFetch()->update(1); // unpauses the texture fetch thread if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time) { break; } } // Update fetch again for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerFetchedTexture* imagep = *iter++; imagep->updateFetch(); } max_time -= timer.getElapsedTimeF32(); max_time = llmax(max_time, .001f); F32 create_time = updateImagesCreateTextures(max_time); LL_DEBUGS("ViewerImages") << "decodeAllImages() took " << timer.getElapsedTimeF32() << " seconds. " << " fetch_pending " << fetch_pending << " create_time " << create_time << LL_ENDL; }