1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
/**
* @file llvocache.h
* @brief Cache of objects on the viewer.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLVOCACHE_H
#define LL_LLVOCACHE_H
#include "lluuid.h"
#include "lldatapacker.h"
#include "lldir.h"
#include "llvieweroctree.h"
#include "llapr.h"
#include "llgltfmaterial.h"
#include <unordered_map>
//---------------------------------------------------------------------------
// Cache entries
class LLCamera;
class LLGLTFOverrideCacheEntry
{
public:
static const std::string VERSION_LABEL;
static const int VERSION;
bool fromLLSD(const LLSD& data);
LLSD toLLSD() const;
LLUUID mObjectId;
U32 mLocalId = 0;
std::unordered_map<S32, LLSD> mSides; //override LLSD per side
std::unordered_map<S32, LLPointer<LLGLTFMaterial> > mGLTFMaterial; //GLTF material per side
U64 mRegionHandle = 0;
};
class LLVOCacheEntry
: public LLViewerOctreeEntryData
{
LL_ALIGN_NEW
public:
enum
{
//low 16-bit state
INACTIVE = 0x00000000, //not visible
IN_QUEUE = 0x00000001, //in visible queue, object to be created
WAITING = 0x00000002, //object creation request sent
ACTIVE = 0x00000004, //object created, and in rendering pipeline.
//high 16-bit state
IN_VO_TREE = 0x00010000, //the entry is in the object cache tree.
LOW_BITS = 0x0000ffff,
HIGH_BITS = 0xffff0000
};
struct CompareVOCacheEntry
{
bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) const
{
F32 lpa = lhs->getSceneContribution();
F32 rpa = rhs->getSceneContribution();
//larger pixel area first
if(lpa > rpa)
{
return true;
}
else if(lpa < rpa)
{
return false;
}
else
{
return lhs < rhs;
}
}
};
protected:
~LLVOCacheEntry();
public:
LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp);
LLVOCacheEntry(LLAPRFile* apr_file);
LLVOCacheEntry();
void updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp);
void clearState(U32 state) {mState &= ~state;}
bool hasState(U32 state) {return mState & state;}
void setState(U32 state);
bool isState(U32 state) {return (mState & LOW_BITS) == state;}
U32 getState() const {return mState & LOW_BITS;}
bool isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold);
U32 getLocalID() const { return mLocalID; }
U32 getCRC() const { return mCRC; }
S32 getHitCount() const { return mHitCount; }
S32 getCRCChangeCount() const { return mCRCChangeCount; }
void calcSceneContribution(const LLVector4a& camera_origin, bool needs_update, U32 last_update, F32 dist_threshold);
void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;}
F32 getSceneContribution() const { return mSceneContrib;}
void dump() const;
S32 writeToBuffer(U8 *data_buffer) const;
LLDataPackerBinaryBuffer *getDP();
void recordHit();
void recordDupe() { mDupeCount++; }
/*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry);
void setParentID(U32 id);
U32 getParentID() const {return mParentID;}
bool isChild() const {return mParentID > 0;}
void addChild(LLVOCacheEntry* entry);
void removeChild(LLVOCacheEntry* entry);
void removeAllChildren();
LLVOCacheEntry* getChild(); //remove the first child, and return it.
S32 getNumOfChildren() const {return mChildrenList.size();}
void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message
void updateParentBoundingInfo();
void saveBoundingSphere();
void setValid(bool valid = true) {mValid = valid;}
bool isValid() const {return mValid;}
void setUpdateFlags(U32 flags) {mUpdateFlags = flags;}
U32 getUpdateFlags() const {return mUpdateFlags;}
static void updateDebugSettings();
static F32 getSquaredPixelThreshold(bool is_front);
private:
void updateParentBoundingInfo(const LLVOCacheEntry* child);
public:
typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t;
typedef std::set<LLVOCacheEntry*> vocache_entry_set_t;
typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t;
typedef std::unordered_map<U32, LLGLTFOverrideCacheEntry> vocache_gltf_overrides_map_t;
S32 mLastCameraUpdated;
protected:
U32 mLocalID;
U32 mParentID;
U32 mCRC;
U32 mUpdateFlags; //receive from sim
S32 mHitCount;
S32 mDupeCount;
S32 mCRCChangeCount;
LLDataPackerBinaryBuffer mDP;
U8 *mBuffer;
F32 mSceneContrib; //projected scene contributuion of this object.
U32 mState; //high 16 bits reserved for special use.
vocache_entry_set_t mChildrenList; //children entries in a linked set.
bool mValid; //if set, this entry is valid, otherwise it is invalid and will be removed.
LLVector4a mBSphereCenter; //bounding sphere center
F32 mBSphereRadius; //bounding sphere radius
public:
static U32 sMinFrameRange;
static F32 sNearRadius;
static F32 sRearFarRadius;
static F32 sFrontPixelThreshold;
static F32 sRearPixelThreshold;
};
class LLVOCacheGroup : public LLOcclusionCullingGroup
{
public:
LLVOCacheGroup(OctreeNode* node, LLViewerOctreePartition* part) : LLOcclusionCullingGroup(node, part){}
//virtual
void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
protected:
virtual ~LLVOCacheGroup();
};
class LLVOCachePartition : public LLViewerOctreePartition
{
public:
LLVOCachePartition(LLViewerRegion* regionp);
virtual ~LLVOCachePartition();
bool addEntry(LLViewerOctreeEntry* entry);
void removeEntry(LLViewerOctreeEntry* entry);
/*virtual*/ S32 cull(LLCamera &camera, bool do_occlusion);
void addOccluders(LLViewerOctreeGroup* gp);
void resetOccluders();
void processOccluders(LLCamera* camera);
void removeOccluder(LLVOCacheGroup* group);
void setCullHistory(bool has_new_object);
bool isFrontCull() const {return mFrontCull;}
private:
void selectBackObjects(LLCamera &camera, F32 projection_area_cutoff, bool use_occlusion); //select objects behind camera.
public:
static bool sNeedsOcclusionCheck;
private:
bool mFrontCull; //the view frustum cull if set, otherwise is back sphere cull.
U32 mCullHistory;
U32 mCulledTime[LLViewerCamera::NUM_CAMERAS];
std::set<LLVOCacheGroup*> mOccludedGroups;
S32 mBackSlectionEnabled; //enable to select back objects if > 0.
U32 mIdleHash;
};
//
//Note: LLVOCache is not thread-safe
//
class LLVOCache : public LLParamSingleton<LLVOCache>
{
LLSINGLETON(LLVOCache, bool read_only);
~LLVOCache() ;
private:
struct HeaderEntryInfo
{
HeaderEntryInfo() : mIndex(0), mHandle(0), mTime(0) {}
S32 mIndex;
U64 mHandle ;
U32 mTime ;
};
struct HeaderMetaInfo
{
HeaderMetaInfo() : mVersion(0), mAddressSize(0) {}
U32 mVersion;
U32 mAddressSize;
};
struct header_entry_less
{
bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const
{
if(lhs->mTime == rhs->mTime)
{
return lhs < rhs ;
}
return lhs->mTime < rhs->mTime ; // older entry in front of queue (set)
}
};
typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;
typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t;
public:
// We need this init to be separate from constructor, since we might construct cache, purge it, then init.
void initCache(ELLPath location, U32 size, U32 cache_version);
void removeCache(ELLPath location, bool started = false) ;
bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map);
void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, bool dirty_cache, bool removal_enabled);
void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, bool dirty_cache, bool removal_enabled);
void removeEntry(U64 handle) ;
void removeGenericExtrasForHandle(U64 handle);
U32 getCacheEntries() { return mNumEntries; }
U32 getCacheEntriesMax() { return mCacheSize; }
private:
void setDirNames(ELLPath location);
// determine the cache filename for the region from the region handle
void getObjectCacheFilename(U64 handle, std::string& filename);
std::string getObjectCacheExtrasFilename(U64 handle);
void removeFromCache(HeaderEntryInfo* entry);
void readCacheHeader();
void writeCacheHeader();
void clearCacheInMemory();
void removeCache() ;
void removeEntry(HeaderEntryInfo* entry) ;
void purgeEntries(U32 size);
bool updateEntry(const HeaderEntryInfo* entry);
private:
bool mEnabled;
bool mInitialized ;
bool mReadOnly ;
HeaderMetaInfo mMetaInfo;
U32 mCacheSize;
U32 mNumEntries;
std::string mHeaderFileName ;
std::string mObjectCacheDirName;
LLVolatileAPRPool* mLocalAPRFilePoolp ;
header_entry_queue_t mHeaderEntryQueue;
handle_entry_map_t mHandleEntryMap;
};
#endif
|