diff options
-rw-r--r-- | indra/newview/llmeshrepository.cpp | 189 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.h | 68 |
2 files changed, 145 insertions, 112 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 663afe64a9..851107b3be 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -544,6 +544,66 @@ bool RequestStats::isDelayed() const return mTimer.getStarted() && !mTimer.hasExpired(); } +F32 calculate_score(LLVOVolume* object) +{ + if (!object) + { + return -1.f; + } + LLDrawable* drawable = object->mDrawable; + if (!drawable) + { + return -1; + } + if (drawable->isState(LLDrawable::RIGGED) || object->isAttachment()) + { + LLVOAvatar* avatar = object->getAvatar(); + LLDrawable* av_drawable = avatar ? avatar->mDrawable : nullptr; + if (avatar && av_drawable) + { + // See LLVOVolume::calcLOD() + F32 radius; + if (avatar->isControlAvatar()) + { + const LLVector3* box = avatar->getLastAnimExtents(); + LLVector3 diag = box[1] - box[0]; + radius = diag.magVec() * 0.5f; + } + else + { + // Volume in a rigged mesh attached to a regular avatar. + const LLVector3* box = avatar->getLastAnimExtents(); + LLVector3 diag = box[1] - box[0]; + radius = diag.magVec(); + + if (!avatar->isSelf() && !avatar->hasFirstFullAttachmentData()) + { + // slightly deprioritize avatars that are still receiving data + radius *= 0.9f; + } + } + return radius / llmax(av_drawable->mDistanceWRTCamera, 1.f); + } + } + return drawable->getRadius() / llmax(drawable->mDistanceWRTCamera, 1.f); +} + +void PendingRequestBase::updateScore() +{ + mScore = 0; + if (mTrackedData) + { + for (LLVOVolume* volume : mTrackedData->mVolumes) + { + F32 cur_score = calculate_score(volume); + if (cur_score > 0) + { + mScore = llmax(mScore, cur_score); + } + } + } +} + LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material) { LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData); @@ -2220,7 +2280,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes if (gMeshRepo.mLoadingSkins.find(mesh_id) == gMeshRepo.mLoadingSkins.end()) { - gMeshRepo.mLoadingSkins[mesh_id] = {}; // add an empty vector to indicate to main thread that we are loading skin info + gMeshRepo.mLoadingSkins[mesh_id]; // add an empty vector to indicate to main thread that we are loading skin info } } @@ -4212,13 +4272,13 @@ void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) { for (auto& param : lod) { - vector_replace_with_last(param.second, vobj); + vector_replace_with_last(param.second.mVolumes, vobj); } } for (auto& skin_pair : mLoadingSkins) { - vector_replace_with_last(skin_pair.second, vobj); + vector_replace_with_last(skin_pair.second.mVolumes, vobj); } } @@ -4241,16 +4301,17 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para mesh_load_map::iterator iter = mLoadingMeshes[new_lod].find(mesh_id); if (iter != mLoadingMeshes[new_lod].end()) { //request pending for this mesh, append volume id to list - auto it = std::find(iter->second.begin(), iter->second.end(), vobj); - if (it == iter->second.end()) { - iter->second.push_back(vobj); + auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), vobj); + if (it == iter->second.mVolumes.end()) { + iter->second.addVolume(vobj); } } else { //first request for this mesh - mLoadingMeshes[new_lod][mesh_id].push_back(vobj); - mPendingRequests.emplace_back(new PendingRequestLOD(mesh_params, new_lod)); + std::shared_ptr<PendingRequestBase> request(new PendingRequestLOD(mesh_params, new_lod)); + mPendingRequests.emplace_back(request); + mLoadingMeshes[new_lod][mesh_id].initData(vobj, request); LLMeshRepository::sLODPending++; } } @@ -4309,50 +4370,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para return new_lod; } -F32 calculate_score(LLVOVolume* object) -{ - if (!object) - { - return -1.f; - } - LLDrawable* drawable = object->mDrawable; - if (!drawable) - { - return -1; - } - if (drawable->isState(LLDrawable::RIGGED) || object->isAttachment()) - { - LLVOAvatar* avatar = object->getAvatar(); - LLDrawable* av_drawable = avatar ? avatar->mDrawable : nullptr; - if (avatar && av_drawable) - { - // See LLVOVolume::calcLOD() - F32 radius; - if (avatar->isControlAvatar()) - { - const LLVector3* box = avatar->getLastAnimExtents(); - LLVector3 diag = box[1] - box[0]; - radius = diag.magVec() * 0.5f; - } - else - { - // Volume in a rigged mesh attached to a regular avatar. - const LLVector3* box = avatar->getLastAnimExtents(); - LLVector3 diag = box[1] - box[0]; - radius = diag.magVec(); - - if (!avatar->isSelf() && !avatar->hasFirstFullAttachmentData()) - { - // slightly deprioritize avatars that are still receiving data - radius *= 0.9f; - } - } - return radius / llmax(av_drawable->mDistanceWRTCamera, 1.f); - } - } - return drawable->getRadius() / llmax(drawable->mDistanceWRTCamera, 1.f); -} - void LLMeshRepository::notifyLoadedMeshes() { //called from main thread LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); @@ -4549,51 +4566,14 @@ void LLMeshRepository::notifyLoadedMeshes() if (mPendingRequests.size() > push_count) { - LL_PROFILE_ZONE_NAMED("Mesh score_map"); + LL_PROFILE_ZONE_NAMED("Mesh score update"); // More requests than the high-water limit allows so // sort and forward the most important. - //calculate "score" for pending requests - - //create score map - std::map<LLUUID, F32> score_map; - - for (U32 i = 0; i < LLVolumeLODGroup::NUM_LODS; ++i) - { - for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) - { - F32 max_score = 0.f; - for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) - { - F32 cur_score = calculate_score(*obj_iter); - if (cur_score >= 0.f) - { - max_score = llmax(max_score, cur_score); - } - } - - score_map[iter->first] = max_score; - } - } - for (mesh_load_map::iterator iter = mLoadingSkins.begin(); iter != mLoadingSkins.end(); ++iter) - { - F32 max_score = 0.f; - for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) - { - F32 cur_score = calculate_score(*obj_iter); - if (cur_score >= 0.f) - { - max_score = llmax(max_score, cur_score); - } - } - - score_map[iter->first] = max_score; - } - - //set "score" for pending requests - for (std::unique_ptr<PendingRequestBase>& req_p : mPendingRequests) + // update "score" for pending requests + for (std::shared_ptr<PendingRequestBase>& req_p : mPendingRequests) { - req_p->setScore(score_map[req_p->getId()]); + req_p->checkScore(); } //sort by "score" @@ -4602,7 +4582,9 @@ void LLMeshRepository::notifyLoadedMeshes() } while (!mPendingRequests.empty() && push_count > 0) { - std::unique_ptr<PendingRequestBase>& req_p = mPendingRequests.front(); + std::shared_ptr<PendingRequestBase>& req_p = mPendingRequests.front(); + // todo: check hasTrackedData here and erase request if none + // since this is supposed to mean that request was removed switch (req_p->getRequestType()) { case MESH_REQUEST_LOD: @@ -4657,7 +4639,7 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info) skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID); if (iter != mLoadingSkins.end()) { - for (LLVOVolume* vobj : iter->second) + for (LLVOVolume* vobj : iter->second.mVolumes) { if (vobj) { @@ -4673,7 +4655,7 @@ void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id) skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); if (iter != mLoadingSkins.end()) { - for (LLVOVolume* vobj : iter->second) + for (LLVOVolume* vobj : iter->second.mVolumes) { if (vobj) { @@ -4737,7 +4719,7 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol } //notify waiting LLVOVolume instances that their requested mesh is available - for (LLVOVolume* vobj : obj_iter->second) + for (LLVOVolume* vobj : obj_iter->second.mVolumes) { if (vobj) { @@ -4767,7 +4749,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, LLPrimitive::getVolumeManager()->unrefVolume(sys_volume); } - for (LLVOVolume* vobj : obj_iter->second) + for (LLVOVolume* vobj : obj_iter->second.mVolumes) { if (vobj) { @@ -4810,16 +4792,17 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOV skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); if (iter != mLoadingSkins.end()) { //request pending for this mesh, append volume id to list - auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj); - if (it == iter->second.end()) { - iter->second.push_back(requesting_obj); + auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), requesting_obj); + if (it == iter->second.mVolumes.end()) { + iter->second.addVolume(requesting_obj); } } else { //first request for this mesh - mLoadingSkins[mesh_id].push_back(requesting_obj); - mPendingRequests.emplace_back(new PendingRequestUUID(mesh_id, MESH_REQUEST_SKIN)); + std::shared_ptr<PendingRequestBase> request(new PendingRequestUUID(mesh_id, MESH_REQUEST_SKIN)); + mLoadingSkins[mesh_id].initData(requesting_obj, request); + mPendingRequests.emplace_back(request); } } } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index b9acb3573f..0847c29d0d 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -168,7 +168,6 @@ public: void submitRequest(Request* request); static S32 llcdCallback(const char*, S32, S32); - void cancel(); void setMeshData(LLCDMeshData& mesh, bool vertex_based); void doDecomposition(); @@ -206,19 +205,19 @@ private: LLFrameTimer mTimer; }; - +class MeshLoadData; class PendingRequestBase { public: struct CompareScoreGreater { - bool operator()(const std::unique_ptr<PendingRequestBase>& lhs, const std::unique_ptr<PendingRequestBase>& rhs) + bool operator()(const std::shared_ptr<PendingRequestBase>& lhs, const std::shared_ptr<PendingRequestBase>& rhs) { return lhs->mScore > rhs->mScore; // greatest = first } }; - PendingRequestBase() : mScore(0.f) {}; + PendingRequestBase() : mScore(0.f), mTrackedData(nullptr), mScoreDirty(true) {}; virtual ~PendingRequestBase() {} bool operator<(const PendingRequestBase& rhs) const @@ -226,14 +225,34 @@ public: return mId < rhs.mId; } - void setScore(F32 score) { mScore = score; } F32 getScore() const { return mScore; } + void checkScore() + { + constexpr F32 EXPIRE_TIME_SECS = 8.f; + if (mScoreTimer.getElapsedTimeF32() > EXPIRE_TIME_SECS || mScoreDirty) + { + updateScore(); + mScoreDirty = false; + mScoreTimer.reset(); + } + }; + LLUUID getId() const { return mId; } virtual EMeshRequestType getRequestType() const = 0; + void trackData(MeshLoadData* data) { mTrackedData = data; mScoreDirty = true; } + void untrackData() { mTrackedData = nullptr; } + bool hasTrackedData() { return mTrackedData != nullptr; } + void setScoreDirty() { mScoreDirty = true; } + protected: - F32 mScore; + void updateScore(); + LLUUID mId; + F32 mScore; + bool mScoreDirty; + LLTimer mScoreTimer; + MeshLoadData* mTrackedData; }; class PendingRequestLOD : public PendingRequestBase @@ -267,6 +286,37 @@ private: EMeshRequestType mRequestType; }; + +class MeshLoadData +{ +public: + MeshLoadData() {} + ~MeshLoadData() + { + if (std::shared_ptr<PendingRequestBase> request = mRequest.lock()) + { + request->untrackData(); + } + } + void initData(LLVOVolume* vol, std::shared_ptr<PendingRequestBase>& request) + { + mVolumes.push_back(vol); + request->trackData(this); + mRequest = request; + } + void addVolume(LLVOVolume* vol) + { + mVolumes.push_back(vol); + if (std::shared_ptr<PendingRequestBase> request = mRequest.lock()) + { + request->setScoreDirty(); + } + } + std::vector<LLVOVolume*> mVolumes; +private: + std::weak_ptr<PendingRequestBase> mRequest; +}; + class LLMeshHeader { public: @@ -814,7 +864,7 @@ public: static void metricsProgress(unsigned int count); static void metricsUpdate(); - typedef std::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map; + typedef std::unordered_map<LLUUID, MeshLoadData> mesh_load_map; mesh_load_map mLoadingMeshes[4]; typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map; @@ -825,11 +875,11 @@ public: LLMutex* mMeshMutex; - typedef std::vector <std::unique_ptr<PendingRequestBase> > pending_requests_vec; + typedef std::vector <std::shared_ptr<PendingRequestBase> > pending_requests_vec; pending_requests_vec mPendingRequests; //list of mesh ids awaiting skin info - typedef std::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map; + typedef std::unordered_map<LLUUID, MeshLoadData > skin_load_map; skin_load_map mLoadingSkins; //list of mesh ids awaiting decompositions |