summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmeshrepository.h')
-rw-r--r--indra/newview/llmeshrepository.h215
1 files changed, 170 insertions, 45 deletions
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index b5c2424578..0d9da32e27 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -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 std::unique_ptr<PendingRequestBase>& lhs, const std::unique_ptr<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 = 0;
+
+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:
@@ -235,19 +307,67 @@ public:
m404 = header.has("404");
}
+private:
+
+ enum EDiskCacheFlags {
+ FLAG_SKIN = 1 << LLModel::NUM_LODS,
+ FLAG_PHYSCONVEX = 1 << (LLModel::NUM_LODS + 1),
+ FLAG_PHYSMESH = 1 << (LLModel::NUM_LODS + 2),
+ };
+public:
+ U32 getFlags()
+ {
+ U32 flags = 0;
+ for (U32 i = 0; i < LLModel::NUM_LODS; i++)
+ {
+ if (mLodInCache[i])
+ {
+ flags |= 1 << i;
+ }
+ }
+ if (mSkinInCache)
+ {
+ flags |= FLAG_SKIN;
+ }
+ if (mPhysicsConvexInCache)
+ {
+ flags |= FLAG_PHYSCONVEX;
+ }
+ if (mPhysicsMeshInCache)
+ {
+ flags |= FLAG_PHYSMESH;
+ }
+ return flags;
+ }
+
+ void setFromFlags(U32 flags)
+ {
+ for (U32 i = 0; i < LLModel::NUM_LODS; i++)
+ {
+ mLodInCache[i] = (flags & (1 << i)) != 0;
+ }
+ mSkinInCache = (flags & FLAG_SKIN) != 0;
+ mPhysicsConvexInCache = (flags & FLAG_PHYSCONVEX) != 0;
+ mPhysicsMeshInCache = (flags & FLAG_PHYSMESH) != 0;
+ }
S32 mVersion = -1;
S32 mSkinOffset = -1;
S32 mSkinSize = -1;
+ bool mSkinInCache = false;
S32 mPhysicsConvexOffset = -1;
S32 mPhysicsConvexSize = -1;
+ bool mPhysicsConvexInCache = false;
S32 mPhysicsMeshOffset = -1;
S32 mPhysicsMeshSize = -1;
+ bool mPhysicsMeshInCache = false;
- S32 mLodOffset[4] = { -1 };
- S32 mLodSize[4] = { -1 };
+ S32 mLodOffset[LLModel::NUM_LODS] = { -1 };
+ S32 mLodSize[LLModel::NUM_LODS] = { -1 };
+ bool mLodInCache[LLModel::NUM_LODS] = { false };
+ S32 mHeaderSize = -1;
bool m404 = false;
};
@@ -256,8 +376,9 @@ class LLMeshRepoThread : public LLThread
{
public:
- volatile static S32 sActiveHeaderRequests;
- volatile static S32 sActiveLODRequests;
+ static std::atomic<S32> sActiveHeaderRequests;
+ static std::atomic<S32> sActiveLODRequests;
+ static std::atomic<S32> sActiveSkinRequests;
static U32 sMaxConcurrentRequests;
static S32 sRequestLowWater;
static S32 sRequestHighWater;
@@ -265,10 +386,13 @@ public:
LLMutex* mMutex;
LLMutex* mHeaderMutex;
+ LLMutex* mLoadedMutex;
+ LLMutex* mPendingMutex;
+ LLMutex* mSkinMapMutex;
LLCondition* mSignal;
//map of known mesh headers
- typedef boost::unordered_map<LLUUID, std::pair<U32, LLMeshHeader>> mesh_header_map; // pair is header_size and data
+ typedef boost::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data
mesh_header_map mMeshHeader;
class HeaderRequest : public RequestStats
@@ -292,19 +416,10 @@ public:
public:
LLVolumeParams mMeshParams;
S32 mLOD;
- F32 mScore;
LODRequest(const LLVolumeParams& mesh_params, S32 lod)
- : RequestStats(), mMeshParams(mesh_params), mLOD(lod), mScore(0.f)
- {
- }
- };
-
- struct CompareScoreGreater
- {
- bool operator()(const LODRequest& lhs, const LODRequest& rhs)
+ : RequestStats(), mMeshParams(mesh_params), mLOD(lod)
{
- return lhs.mScore > rhs.mScore; // greatest = first
}
};
@@ -369,7 +484,7 @@ public:
std::deque<LoadedMesh> mLoadedQ;
//map of pending header requests and currently desired LODs
- typedef std::unordered_map<LLUUID, std::vector<S32> > pending_lod_map;
+ typedef std::unordered_map<LLUUID, std::array<S32, LLModel::NUM_LODS> > pending_lod_map;
pending_lod_map mPendingLOD;
// map of mesh ID to skin info (mirrors LLMeshRepository::mSkinMap)
@@ -379,6 +494,8 @@ public:
// workqueue for processing generic requests
LL::WorkQueue mWorkQueue;
+ // lods have their own thread due to costly cacheOptimize() calls
+ std::unique_ptr<LL::ThreadPool> mMeshThreadPool;
// llcorehttp library interface objects.
LLCore::HttpStatus mHttpStatus;
@@ -402,16 +519,16 @@ public:
void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
- bool fetchMeshHeader(const LLVolumeParams& mesh_params, bool can_retry = true);
- bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool can_retry = true);
- EMeshProcessingResult headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
+ bool fetchMeshHeader(const LLVolumeParams& mesh_params);
+ bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ EMeshProcessingResult headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size, U32 flags = 0);
EMeshProcessingResult lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- bool hasPhysicsShapeInHeader(const LLUUID& mesh_id);
- bool hasSkinInfoInHeader(const LLUUID& mesh_id);
- bool hasHeader(const LLUUID& mesh_id);
+ bool hasPhysicsShapeInHeader(const LLUUID& mesh_id) const;
+ bool hasSkinInfoInHeader(const LLUUID& mesh_id) const;
+ bool hasHeader(const LLUUID& mesh_id) const;
void notifyLoadedMeshes();
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
@@ -422,7 +539,7 @@ public:
//send request for skin info, returns true if header info exists
// (should hold onto mesh_id and try again later if header info does not exist)
- bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);
+ bool fetchMeshSkinInfo(const LLUUID& mesh_id);
//send request for decomposition, returns true if header info exists
// (should hold onto mesh_id and try again later if header info does not exist)
@@ -436,6 +553,8 @@ public:
static void decActiveLODRequests();
static void incActiveHeaderRequests();
static void decActiveHeaderRequests();
+ static void incActiveSkinRequests();
+ static void decActiveSkinRequests();
// Set the caps strings and preferred version for constructing
// mesh fetch URLs.
@@ -456,6 +575,14 @@ private:
LLCore::HttpHandle getByteRange(const std::string & url,
size_t offset, size_t len,
const LLCore::HttpHandler::ptr_t &handler);
+
+ // Mutex: acquires mPendingMutex, mMutex and mHeaderMutex as needed
+ void loadMeshLOD(const LLUUID &mesh_id, const LLVolumeParams& mesh_params, S32 lod);
+
+ // Threads: Repo thread only
+ U8* getDiskCacheBuffer(S32 size);
+ S32 mDiskCacheBufferSize = 0;
+ U8* mDiskCacheBuffer = nullptr;
};
@@ -568,35 +695,35 @@ public:
bool init(const LLMeshHeader& header);
// Size for given LOD
- S32 getSizeByLOD(S32 lod);
+ S32 getSizeByLOD(S32 lod) const;
// Sum of all LOD sizes.
- S32 getSizeTotal();
+ S32 getSizeTotal() const;
// Estimated triangle counts for the given LOD.
- F32 getEstTrisByLOD(S32 lod);
+ F32 getEstTrisByLOD(S32 lod) const;
// Estimated triangle counts for the largest LOD. Typically this
// is also the "high" LOD, but not necessarily.
- F32 getEstTrisMax();
+ F32 getEstTrisMax() const;
// Triangle count as computed by original streaming cost
// formula. Triangles in each LOD are weighted based on how
// frequently they will be seen.
// This was called "unscaled_value" in the original getStreamingCost() functions.
- F32 getRadiusWeightedTris(F32 radius);
+ F32 getRadiusWeightedTris(F32 radius) const;
// Triangle count used by triangle-based cost formula. Based on
// triangles in highest LOD plus potentially partial charges for
// lower LODs depending on complexity.
- F32 getEstTrisForStreamingCost();
+ F32 getEstTrisForStreamingCost() const;
// Streaming cost. This should match the server-side calculation
// for the corresponding volume.
- F32 getRadiusBasedStreamingCost(F32 radius);
+ F32 getRadiusBasedStreamingCost(F32 radius) const;
// New streaming cost formula, currently only used for animated objects.
- F32 getTriangleBasedStreamingCost();
+ F32 getTriangleBasedStreamingCost() const;
private:
// From the "size" field of the mesh header. LOD 0=lowest, 3=highest.
@@ -620,12 +747,12 @@ public:
static U32 sLODPending;
static U32 sLODProcessing;
static U32 sCacheBytesRead;
- static U32 sCacheBytesWritten;
+ static std::atomic<U32> sCacheBytesWritten;
static U32 sCacheBytesHeaders;
static U32 sCacheBytesSkins;
static U32 sCacheBytesDecomps;
static U32 sCacheReads;
- static U32 sCacheWrites;
+ static std::atomic<U32> sCacheWrites;
static U32 sMaxLockHoldoffs; // Maximum sequential locking failures
static LLDeadmanTimer sQuiescentTimer; // Time-to-complete-mesh-downloads after significant events
@@ -646,11 +773,11 @@ public:
void unregisterMesh(LLVOVolume* volume);
//mesh management functions
- S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
+ S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 new_lod = 0, S32 last_lod = -1);
void notifyLoadedMeshes();
- void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
- void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
+ void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume, S32 lod);
+ void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 request_lod, S32 volume_lod);
void notifySkinInfoReceived(LLMeshSkinInfo* info);
void notifySkinInfoUnavailable(const LLUUID& info);
void notifyDecompositionReceived(LLModel::Decomposition* info);
@@ -662,7 +789,7 @@ public:
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);
bool hasSkinInfo(const LLUUID& mesh_id);
- bool hasHeader(const LLUUID& mesh_id);
+ bool hasHeader(const LLUUID& mesh_id) const;
void buildHull(const LLVolumeParams& params, S32 detail);
void buildPhysicsMesh(LLModel::Decomposition& decomp);
@@ -676,7 +803,7 @@ public:
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()),
LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
- S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
+ S32 getMeshSize(const LLUUID& mesh_id, S32 lod) const;
// Quiescent timer management, main thread only.
static void metricsStart();
@@ -684,7 +811,7 @@ public:
static void metricsProgress(unsigned int count);
static void metricsUpdate();
- typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;
+ typedef std::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;
mesh_load_map mLoadingMeshes[4];
typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map;
@@ -695,15 +822,13 @@ public:
LLMutex* mMeshMutex;
- std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
+ typedef std::vector <std::unique_ptr<PendingRequestBase> > pending_requests_vec;
+ pending_requests_vec mPendingRequests;
//list of mesh ids awaiting skin info
- typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;
+ typedef std::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;