#1186 Make lod and skin request share priorities

skins are needed to decloud avatars as much as lods
meow-7.2.2
Andrey Kleshchev 2024-11-11 20:53:50 +02:00
parent 5029f0322f
commit 8f274bfdf9
2 changed files with 165 additions and 74 deletions

View File

@ -925,7 +925,7 @@ void LLMeshRepoThread::run()
}
sRequestWaterLevel = static_cast<S32>(mHttpRequestSet.size()); // Stats data update
// NOTE: order of queue processing intentionally favors LOD requests over header requests
// NOTE: order of queue processing intentionally favors LOD and Skin requests over header requests
// Todo: we are processing mLODReqQ, mHeaderReqQ, mSkinRequests, mDecompositionRequests and mPhysicsShapeRequests
// in relatively similar manners, remake code to simplify/unify the process,
// like processRequests(&requestQ, fetchFunction); which does same thing for each element
@ -979,6 +979,50 @@ void LLMeshRepoThread::run()
}
}
if (mHttpRequestSet.size() < sRequestHighWater
&& !mSkinRequests.empty())
{
if (!mSkinRequests.empty())
{
std::list<UUIDBasedRequest> incomplete;
while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
{
mMutex->lock();
auto req = mSkinRequests.front();
mSkinRequests.pop_front();
mMutex->unlock();
if (req.isDelayed())
{
incomplete.emplace_back(req);
}
else if (!fetchMeshSkinInfo(req.mId, req.canRetry()))
{
if (req.canRetry())
{
req.updateTime();
incomplete.emplace_back(req);
}
else
{
LLMutexLock locker(mMutex);
mSkinUnavailableQ.push_back(req);
LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL;
}
}
}
if (!incomplete.empty())
{
LLMutexLock locker(mMutex);
for (const auto& req : incomplete)
{
mSkinRequests.push_back(req);
}
}
}
}
if (!mHeaderReqQ.empty() && mHttpRequestSet.size() < sRequestHighWater)
{
std::list<HeaderRequest> incomplete;
@ -1028,54 +1072,13 @@ void LLMeshRepoThread::run()
// performing long-duration actions.
if (mHttpRequestSet.size() < sRequestHighWater
&& (!mSkinRequests.empty()
|| !mDecompositionRequests.empty()
&& (!mDecompositionRequests.empty()
|| !mPhysicsShapeRequests.empty()))
{
// Something to do probably, lock and double-check. We don't want
// to hold the lock long here. That will stall main thread activities
// so we bounce it.
if (!mSkinRequests.empty())
{
std::list<UUIDBasedRequest> incomplete;
while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
{
mMutex->lock();
auto req = mSkinRequests.front();
mSkinRequests.pop_front();
mMutex->unlock();
if (req.isDelayed())
{
incomplete.emplace_back(req);
}
else if (!fetchMeshSkinInfo(req.mId, req.canRetry()))
{
if (req.canRetry())
{
req.updateTime();
incomplete.emplace_back(req);
}
else
{
LLMutexLock locker(mMutex);
mSkinUnavailableQ.push_back(req);
LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL;
}
}
}
if (!incomplete.empty())
{
LLMutexLock locker(mMutex);
for (const auto& req : incomplete)
{
mSkinRequests.push_back(req);
}
}
}
// holding lock, try next list
// *TODO: For UI/debug-oriented lists, we might drop the fine-
// grained locking as there's a lowered expectation of smoothness
@ -1195,7 +1198,6 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32
}
}
void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
{ //could be called from any thread
const LLUUID& mesh_id = mesh_params.getSculptID();
@ -3738,7 +3740,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
{
//first request for this mesh
mLoadingMeshes[detail][mesh_id].push_back(vobj);
mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));
mPendingRequests.push_back(PendingRequestLOD(mesh_params, detail));
LLMeshRepository::sLODPending++;
}
}
@ -4011,35 +4013,64 @@ void LLMeshRepository::notifyLoadedMeshes()
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)
{
LLVOVolume* object = *obj_iter;
if (object)
{
LLDrawable* drawable = object->mDrawable;
if (drawable)
{
F32 cur_score = drawable->getRadius() / llmax(drawable->mDistanceWRTCamera, 1.f);
max_score = llmax(max_score, cur_score);
}
}
}
score_map[iter->first] = max_score;
}
//set "score" for pending requests
for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
for (std::vector<PendingRequestBase>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
{
iter->mScore = score_map[iter->mMeshParams.getSculptID()];
iter->setScore(score_map[iter->getId()]);
}
//sort by "score"
std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count,
mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
mPendingRequests.end(), PendingRequestBase::CompareScoreGreater());
}
while (!mPendingRequests.empty() && push_count > 0)
{
LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
PendingRequestBase& request = mPendingRequests.front();
switch (request.getRequestType())
{
case MESH_REQUEST_LOD:
{
PendingRequestLOD& lod = (PendingRequestLOD&)request;
mThread->loadMeshLOD(lod.mMeshParams, lod.mLOD);
LLMeshRepository::sLODPending--;
break;
}
case MESH_REQUEST_SKIN:
{
PendingRequestUUID& skin = (PendingRequestUUID&)request;
mThread->loadMeshSkinInfo(skin.getId());
break;
}
default:
break;
}
mPendingRequests.erase(mPendingRequests.begin());
LLMeshRepository::sLODPending--;
push_count--;
}
}
//send skin info requests
while (!mPendingSkinRequests.empty())
{
mThread->loadMeshSkinInfo(mPendingSkinRequests.front());
mPendingSkinRequests.pop();
}
//send decomposition requests
while (!mPendingDecompositionRequests.empty())
{
@ -4231,7 +4262,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOV
{
//first request for this mesh
mLoadingSkins[mesh_id].push_back(requesting_obj);
mPendingSkinRequests.push(mesh_id);
mPendingRequests.push_back(PendingRequestUUID(mesh_id, MESH_REQUEST_SKIN));
}
}
}

View File

@ -63,6 +63,16 @@ typedef enum e_mesh_processing_result_enum
MESH_UNKNOWN
} EMeshProcessingResult;
typedef enum e_mesh_request_type_enum
{
MESH_REQUEST_HEADER,
MESH_REQUEST_LOD,
MESH_REQUEST_SKIN,
MESH_REQUEST_DECOMPOSITION,
MESH_REQUEST_PHYSICS,
MESH_REQUEST_UKNOWN
} EMeshRequestType;
class LLMeshUploadData
{
public:
@ -183,7 +193,8 @@ public:
class RequestStats
{
public:
RequestStats() : mRetries(0) {};
RequestStats() :mRetries(0) {};
void updateTime();
bool canRetry() const;
@ -195,6 +206,67 @@ private:
LLFrameTimer mTimer;
};
class PendingRequestBase
{
public:
struct CompareScoreGreater
{
bool operator()(const PendingRequestBase& lhs, const PendingRequestBase& rhs)
{
return lhs.mScore > rhs.mScore; // greatest = first
}
};
PendingRequestBase() : mScore(0.f) {};
virtual ~PendingRequestBase() {}
bool operator<(const PendingRequestBase& rhs) const
{
return mId < rhs.mId;
}
void setScore(F32 score) { mScore = score; }
F32 getScore() const { return mScore; }
LLUUID getId() const { return mId; }
virtual EMeshRequestType getRequestType() const { return MESH_REQUEST_UKNOWN; }
protected:
F32 mScore;
LLUUID mId;
};
class PendingRequestLOD : public PendingRequestBase
{
public:
LLVolumeParams mMeshParams;
S32 mLOD;
PendingRequestLOD(const LLVolumeParams& mesh_params, S32 lod)
: PendingRequestBase(), mMeshParams(mesh_params), mLOD(lod)
{
mId = mMeshParams.getSculptID();
}
EMeshRequestType getRequestType() const override { return MESH_REQUEST_LOD; }
};
class PendingRequestUUID : public PendingRequestBase
{
public:
PendingRequestUUID(const LLUUID& id, EMeshRequestType type)
: PendingRequestBase(), mRequestType(type)
{
mId = id;
}
EMeshRequestType getRequestType() const override { return mRequestType; }
private:
EMeshRequestType mRequestType;
};
class LLMeshHeader
{
public:
@ -292,22 +364,13 @@ public:
public:
LLVolumeParams mMeshParams;
S32 mLOD;
F32 mScore;
LODRequest(const LLVolumeParams& mesh_params, S32 lod)
: RequestStats(), mMeshParams(mesh_params), mLOD(lod), mScore(0.f)
: RequestStats(), mMeshParams(mesh_params), mLOD(lod)
{
}
};
struct CompareScoreGreater
{
bool operator()(const LODRequest& lhs, const LODRequest& rhs)
{
return lhs.mScore > rhs.mScore; // greatest = first
}
};
class UUIDBasedRequest : public RequestStats
{
public:
@ -695,15 +758,12 @@ public:
LLMutex* mMeshMutex;
std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
std::vector<PendingRequestBase> mPendingRequests;
//list of mesh ids awaiting skin info
typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;
skin_load_map mLoadingSkins;
//list of mesh ids that need to send skin info fetch requests
std::queue<LLUUID> mPendingSkinRequests;
//list of mesh ids awaiting decompositions
std::unordered_set<LLUUID> mLoadingDecompositions;