llvocache.cpp 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201
  1. /**
  2. * @file llvocache.cpp
  3. * @brief Cache of objects on the viewer.
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewergpl$
  6. *
  7. * Copyright (c) 2003-2016 (original implementation), Linden Research, Inc.
  8. * Copyright (c) 2022 (PBR extra data implementation), Linden Research, Inc.
  9. * Copyright (c) 2016-2023, Henri Beauchamp (debugging, cache parameters
  10. * biasing based on memory usage, removal of APR dependency, threading).
  11. *
  12. * Second Life Viewer Source Code
  13. * The source code in this file ("Source Code") is provided by Linden Lab
  14. * to you under the terms of the GNU General Public License, version 2.0
  15. * ("GPL"), unless you have obtained a separate licensing agreement
  16. * ("Other License"), formally executed by you and Linden Lab. Terms of
  17. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  18. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  19. *
  20. * There are special exceptions to the terms and conditions of the GPL as
  21. * it is applied to this Source Code. View the full text of the exception
  22. * in the file doc/FLOSS-exception.txt in this software distribution, or
  23. * online at
  24. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  25. *
  26. * By copying, modifying or distributing this software, you acknowledge
  27. * that you have read and understood your obligations described above,
  28. * and agree to abide by those obligations.
  29. *
  30. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  31. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  32. * COMPLETENESS OR PERFORMANCE.
  33. * $/LicenseInfo$
  34. */
  35. #include "llviewerprecompiledheaders.h"
  36. #include "llvocache.h"
  37. #include "lldir.h"
  38. #include "lldiriterator.h"
  39. #include "llfasttimer.h"
  40. #include "llregionhandle.h"
  41. #include "llsdserialize.h"
  42. #include "llsdutil.h" // For ll_pretty_print_sd()
  43. #include "hbtracy.h"
  44. #include "llagent.h"
  45. #include "llappviewer.h"
  46. #include "lldrawable.h"
  47. #include "llgridmanager.h"
  48. #include "llpipeline.h"
  49. #include "llviewercamera.h"
  50. #include "llviewercontrol.h"
  51. #include "llviewerobjectlist.h"
  52. #include "llviewerregion.h"
  53. #include "llviewertexture.h" // For sDesiredDiscardBias
  54. // Version of our object cache: increment each time its structure changes.
  55. // Note: we use an unusually large number, which should ensure that no cache
  56. // written by another viewer than the Cool VL Viewer would be considered valid
  57. // (even though the cache directory is normally already different).
  58. constexpr U32 OBJECT_CACHE_VERSION = 10002U;
  59. constexpr U32 ADDRESS_SIZE = 64U;
  60. #if HB_AJUSTED_VOCACHE_PARAMETERS
  61. // This is a target FPS rate that is used as a scaler but that is normalized
  62. // with the actual frame rate (1.f / gFrameIntervalSeconds).
  63. constexpr S32 TARGET_FPS = 30;
  64. constexpr F32 FRAME_MS_TARGET = 1.f / (F32)TARGET_FPS;
  65. #endif
  66. // Static variables
  67. U32 LLVOCacheEntry::sMinFrameRange = 0;
  68. F32 LLVOCacheEntry::sNearRadius = 1.f;
  69. F32 LLVOCacheEntry::sRearFarRadius = 1.f;
  70. F32 LLVOCacheEntry::sFrontPixelThreshold = 1.f;
  71. F32 LLVOCacheEntry::sRearPixelThreshold = 1.f;
  72. #if HB_AJUSTED_VOCACHE_PARAMETERS
  73. bool LLVOCacheEntry::sBiasedRetention = false;
  74. #endif
  75. bool LLVOCachePartition::sNeedsOcclusionCheck = false;
  76. bool check_read(LLFile* infile, U8* src, S32 bytes)
  77. {
  78. // Note: eof() is true when getStream() is NULL, so there is no need to
  79. // test for the latter. HB
  80. return src && !infile->eof() && infile->read(src, bytes) == bytes;
  81. }
  82. bool check_write(LLFile* outfile, U8* dst, S32 bytes)
  83. {
  84. return outfile->getStream() && dst && outfile->write(dst, bytes) == bytes;
  85. }
  86. //---------------------------------------------------------------------------
  87. // LLGLTFOverrideCacheEntry
  88. //---------------------------------------------------------------------------
  89. bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data)
  90. {
  91. if (!data.has("local_id") || !data.has("region_handle_x") ||
  92. !data.has("region_handle_y"))
  93. {
  94. LL_DEBUGS("ObjectCache") << "Missing data. local_id: "
  95. << data.has("local_id")
  96. << " - region_handle_x: "
  97. << data.has("region_handle_x")
  98. << " - region_handle_y: "
  99. << data.has("region_handle_y")
  100. << LL_ENDL;
  101. return false;
  102. }
  103. mLocalId = data["local_id"].asInteger();
  104. U32 region_x = data["region_handle_x"].asInteger();
  105. U32 region_y = data["region_handle_y"].asInteger();
  106. mRegionHandle = to_region_handle(region_x, region_y);
  107. // Data format for GLTF materials as follow:
  108. // - "sides" is a list of face indices;
  109. // - "gltf_llsd" is a list of corresponding GLTF override LLSD.
  110. // Any side not represented in "sides" has no override.
  111. if (!data.has("sides") || !data.has("gltf_llsd"))
  112. {
  113. return true; // No GLTF material for this object. It is fine !
  114. }
  115. const LLSD& sides = data.get("sides");
  116. const LLSD& gltf_llsd = data.get("gltf_llsd");
  117. size_t num_sides = sides.size();
  118. if (!num_sides || num_sides != gltf_llsd.size() || !sides.isArray() ||
  119. !gltf_llsd.isArray())
  120. {
  121. llwarns << "Invalid data for object with local id: " << mLocalId
  122. << llendl;
  123. return false;
  124. }
  125. for (size_t i = 0; i < num_sides; ++i)
  126. {
  127. S32 side_idx = sides[i].asInteger();
  128. const LLSD& gltf_mat_llsd = gltf_llsd[i];
  129. mSides[side_idx] = gltf_mat_llsd;
  130. LLGLTFMaterial* matp = new LLGLTFMaterial();
  131. matp->applyOverrideLLSD(gltf_mat_llsd);
  132. mGLTFMaterial[side_idx] = matp;
  133. }
  134. return true;
  135. }
  136. LLSD LLGLTFOverrideCacheEntry::toLLSD() const
  137. {
  138. LLSD data;
  139. data["local_id"] = (LLSD::Integer)mLocalId;
  140. U32 region_x, region_y;
  141. from_region_handle(mRegionHandle, &region_x, &region_y);
  142. data["region_handle_x"] = (LLSD::Integer)region_x;
  143. data["region_handle_y"] = (LLSD::Integer)region_y;
  144. for (data_map_t::const_iterator it = mSides.begin(), end = mSides.end();
  145. it != end; ++it)
  146. {
  147. data["sides"].append(LLSD::Integer(it->first));
  148. data["gltf_llsd"].append(it->second);
  149. }
  150. return data;
  151. }
  152. //---------------------------------------------------------------------------
  153. // LLVOCacheEntry
  154. //---------------------------------------------------------------------------
  155. LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc,
  156. LLDataPackerBinaryBuffer& dp)
  157. : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
  158. mLocalID(local_id),
  159. mCRC(crc),
  160. mUpdateFlags(-1),
  161. mHitCount(0),
  162. mDupeCount(0),
  163. mCRCChangeCount(0),
  164. mState(INACTIVE),
  165. mSceneContrib(0.f),
  166. mValid(true),
  167. mParentID(0),
  168. mBSphereRadius(-1.f)
  169. {
  170. mBuffer = new U8[dp.getBufferSize()];
  171. mDP.assignBuffer(mBuffer, dp.getBufferSize());
  172. mDP = dp;
  173. }
  174. LLVOCacheEntry::LLVOCacheEntry()
  175. : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
  176. mLocalID(0),
  177. mCRC(0),
  178. mUpdateFlags(-1),
  179. mHitCount(0),
  180. mDupeCount(0),
  181. mCRCChangeCount(0),
  182. mBuffer(NULL),
  183. mState(INACTIVE),
  184. mSceneContrib(0.f),
  185. mValid(true),
  186. mParentID(0),
  187. mBSphereRadius(-1.f)
  188. {
  189. mDP.assignBuffer(mBuffer, 0);
  190. }
  191. LLVOCacheEntry::LLVOCacheEntry(LLFile* infile)
  192. : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
  193. mBuffer(NULL),
  194. mUpdateFlags(-1),
  195. mState(INACTIVE),
  196. mSceneContrib(0.f),
  197. mValid(false),
  198. mParentID(0),
  199. mBSphereRadius(-1.f)
  200. {
  201. mDP.assignBuffer(mBuffer, 0);
  202. S32 size = -1;
  203. static U32 data_buffer[6];
  204. bool success = check_read(infile, (U8*)data_buffer, 6 * sizeof(U32));
  205. if (success)
  206. {
  207. U32* ptr = data_buffer;
  208. mLocalID = *ptr++;
  209. mCRC = *ptr++;
  210. mHitCount = (S32)*ptr++;
  211. mDupeCount = (S32)*ptr++;
  212. mCRCChangeCount = (S32)*ptr++;
  213. size = (S32)*ptr;
  214. if (size > 10000 || size < 1) // Corruption in the cache entries ?
  215. {
  216. // We have got a bogus size, skip reading it. We will not bother
  217. // seeking, because the rest of this file is likely bogus, and will
  218. // be tossed anyway.
  219. llwarns << "Bogus cache entry, size " << size << ", aborting !"
  220. << llendl;
  221. success = false;
  222. }
  223. }
  224. if (success && size > 0)
  225. {
  226. mBuffer = new U8[size];
  227. success = check_read(infile, mBuffer, size);
  228. if (success)
  229. {
  230. mDP.assignBuffer(mBuffer, size);
  231. }
  232. else
  233. {
  234. delete[] mBuffer;
  235. mBuffer = NULL;
  236. }
  237. }
  238. if (!success)
  239. {
  240. mLocalID = 0;
  241. mCRC = 0;
  242. mHitCount = 0;
  243. mDupeCount = 0;
  244. mCRCChangeCount = 0;
  245. mBuffer = NULL;
  246. mEntry = NULL;
  247. mState = INACTIVE;
  248. }
  249. }
  250. LLVOCacheEntry::~LLVOCacheEntry()
  251. {
  252. mDP.freeBuffer();
  253. }
  254. void LLVOCacheEntry::updateEntry(U32 crc, LLDataPackerBinaryBuffer& dp)
  255. {
  256. if (mCRC != crc)
  257. {
  258. mCRC = crc;
  259. ++mCRCChangeCount;
  260. }
  261. mDP.freeBuffer();
  262. llassert_always(dp.getBufferSize() > 0);
  263. mBuffer = new U8[dp.getBufferSize()];
  264. mDP.assignBuffer(mBuffer, dp.getBufferSize());
  265. mDP = dp;
  266. }
  267. void LLVOCacheEntry::setParentID(U32 id)
  268. {
  269. if (mParentID != id)
  270. {
  271. removeAllChildren();
  272. mParentID = id;
  273. }
  274. }
  275. void LLVOCacheEntry::removeAllChildren()
  276. {
  277. if (mChildrenList.empty())
  278. {
  279. return;
  280. }
  281. for (set_t::iterator iter = mChildrenList.begin(),
  282. end = mChildrenList.end();
  283. iter != end; ++iter)
  284. {
  285. LLVOCacheEntry* entry = *iter;
  286. if (entry) // Paranoia
  287. {
  288. entry->setParentID(0);
  289. }
  290. }
  291. mChildrenList.clear();
  292. }
  293. //virtual
  294. void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry)
  295. {
  296. if (!entry && mDP.getBufferSize() > 0)
  297. {
  298. LLUUID fullid;
  299. LLViewerObject::unpackUUID(&mDP, fullid, "ID");
  300. LLViewerObject* obj = gObjectList.findObject(fullid);
  301. if (obj && obj->mDrawable)
  302. {
  303. entry = obj->mDrawable->getEntry();
  304. }
  305. }
  306. LLViewerOctreeEntryData::setOctreeEntry(entry);
  307. }
  308. void LLVOCacheEntry::setState(U32 state)
  309. {
  310. if (state > LOW_BITS) // special states
  311. {
  312. mState |= HIGH_BITS & state;
  313. return;
  314. }
  315. // Otherwise LOW_BITS states
  316. clearState(LOW_BITS);
  317. mState |= (LOW_BITS & state);
  318. if (getState() == ACTIVE)
  319. {
  320. #if HB_AJUSTED_VOCACHE_PARAMETERS
  321. F32 fps_ratio_to_target = F32_MAX;
  322. if (gFrameIntervalSeconds > 0.f)
  323. {
  324. fps_ratio_to_target = FRAME_MS_TARGET / gFrameIntervalSeconds;
  325. }
  326. S32 min_interval = llmin((S32)((64.f + (F32)sMinFrameRange) *
  327. fps_ratio_to_target), 10);
  328. #else
  329. S32 min_interval = 64 + sMinFrameRange;
  330. #endif
  331. S32 last_visible = getVisible();
  332. setVisible();
  333. S32 cur_visible = getVisible();
  334. if (cur_visible - last_visible > min_interval ||
  335. cur_visible < min_interval)
  336. {
  337. mLastCameraUpdated = 0; // Reset
  338. }
  339. else
  340. {
  341. mLastCameraUpdated = LLViewerRegion::sLastCameraUpdated;
  342. }
  343. }
  344. }
  345. void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
  346. {
  347. if (!entry || !entry->getEntry() || entry->getParentID() != mLocalID)
  348. {
  349. llassert(false);
  350. return;
  351. }
  352. mChildrenList.insert(entry);
  353. // Update parent bbox
  354. if (getEntry() && isState(INACTIVE))
  355. {
  356. updateParentBoundingInfo(entry);
  357. resetVisible();
  358. }
  359. }
  360. void LLVOCacheEntry::removeChild(LLVOCacheEntry* entry)
  361. {
  362. entry->setParentID(0);
  363. set_t::iterator iter = mChildrenList.find(entry);
  364. if (iter != mChildrenList.end())
  365. {
  366. mChildrenList.erase(iter);
  367. }
  368. }
  369. // Removes the first child and returns it.
  370. LLVOCacheEntry* LLVOCacheEntry::getChild()
  371. {
  372. LLVOCacheEntry* child = NULL;
  373. set_t::iterator iter = mChildrenList.begin();
  374. if (iter != mChildrenList.end())
  375. {
  376. child = *iter;
  377. mChildrenList.erase(iter);
  378. }
  379. return child;
  380. }
  381. LLDataPackerBinaryBuffer* LLVOCacheEntry::getDP()
  382. {
  383. return mDP.getBufferSize() ? &mDP : NULL;
  384. }
  385. void LLVOCacheEntry::dump() const
  386. {
  387. llinfos << "local " << mLocalID << " crc " << mCRC << " hits " << mHitCount
  388. << " dupes " << mDupeCount << " change " << mCRCChangeCount
  389. << llendl;
  390. }
  391. bool LLVOCacheEntry::writeToFile(LLFile* outfile) const
  392. {
  393. if (!mBuffer)
  394. {
  395. llwarns << "NULL buffer for id " << mLocalID << llendl;
  396. return false;
  397. }
  398. S32 size = mDP.getBufferSize();
  399. if (size > 10000 || size < 1)
  400. {
  401. llwarns << "Invalid object cache entry size (" << size << ") for id "
  402. << mLocalID << llendl;
  403. return false;
  404. }
  405. static U32 data_buffer[6];
  406. U32* ptr = data_buffer;
  407. *ptr++ = mLocalID;
  408. *ptr++ = mCRC;
  409. *ptr++ = (U32)mHitCount;
  410. *ptr++ = (U32)mDupeCount;
  411. *ptr++ = (U32)mCRCChangeCount;
  412. *ptr = (U32)size;
  413. if (!check_write(outfile, (U8*)data_buffer, 6 * sizeof(U32)))
  414. {
  415. llwarns << "Failed to write cache entry header for id " << mLocalID
  416. << llendl;
  417. return false;
  418. }
  419. if (!check_write(outfile, (U8*)mBuffer, size))
  420. {
  421. llwarns << "Failed to write cache entry body for id " << mLocalID
  422. << llendl;
  423. return false;
  424. }
  425. return outfile->flush();
  426. }
  427. //static
  428. void LLVOCacheEntry::updateSettings()
  429. {
  430. F32 draw_distance = gAgent.mDrawDistance;
  431. // The number of frames invisible objects stay in memory
  432. static LLCachedControl<U32> inv_obj_time(gSavedSettings,
  433. "NonVisibleObjectsInMemoryTime");
  434. #if HB_AJUSTED_VOCACHE_PARAMETERS
  435. // Whether or not we use the texture discard bias to bias the objects
  436. // retention, thus lowering the memory consumption by cached objects when
  437. // the textures memory usage gets higher.
  438. static LLCachedControl<bool> biased(gSavedSettings,
  439. "BiasedObjectRetention");
  440. sBiasedRetention = biased;
  441. // Make 0 to be the maximum
  442. sMinFrameRange = (inv_obj_time * TARGET_FPS) - 1;
  443. #else
  444. sMinFrameRange = inv_obj_time - 1;
  445. #endif
  446. LL_DEBUGS("ObjectCache") << "Min frame range = " << sMinFrameRange
  447. << " frames." << LL_ENDL;
  448. // Min radius: all objects within this radius remain loaded in memory
  449. static LLCachedControl<F32> min_radius(gSavedSettings,
  450. "SceneLoadMinRadius");
  451. // Cannot exceed the draw distance
  452. sNearRadius = llmin((F32)min_radius, draw_distance);
  453. sNearRadius = llmax(sNearRadius, 1.f); // Minimum value is 1m
  454. LL_DEBUGS("ObjectCache") << "Near radius = " << sNearRadius << "m."
  455. << LL_ENDL;
  456. // Objects within the view frustum whose visible area is greater than this
  457. // threshold will be loaded
  458. static LLCachedControl<F32> front_pixel_threshold(gSavedSettings,
  459. "SceneLoadFrontPixelThreshold");
  460. sFrontPixelThreshold = front_pixel_threshold;
  461. LL_DEBUGS("ObjectCache") << "Front objects threshold = "
  462. << sFrontPixelThreshold << " pixels." << LL_ENDL;
  463. // Objects out of the view frustum whose visible area is greater than this
  464. // threshold will remain loaded
  465. static LLCachedControl<F32> rear_pixel_threshold(gSavedSettings,
  466. "SceneLoadRearPixelThreshold");
  467. sRearPixelThreshold = rear_pixel_threshold;
  468. // Cannot be smaller than sFrontPixelThreshold.
  469. sRearPixelThreshold = llmax(sRearPixelThreshold, sFrontPixelThreshold);
  470. LL_DEBUGS("ObjectCache") << "Rear objects threshold = "
  471. << sRearPixelThreshold << " pixels." << LL_ENDL;
  472. // A percentage of draw distance beyond which all objects outside of view
  473. // frustum will be unloaded, regardless of pixel threshold
  474. static LLCachedControl<F32> rear_max_radius_frac(gSavedSettings,
  475. "SceneLoadRearMaxRadiusFraction");
  476. // Minimum value is 1m
  477. sRearFarRadius = llmax((F32)rear_max_radius_frac * draw_distance / 100.f,
  478. 1.f);
  479. // Cannot be less than "SceneLoadMinRadius".
  480. sRearFarRadius = llmax(sRearFarRadius, (F32)min_radius);
  481. // Cannot be more than the draw distance.
  482. sRearFarRadius = llmin(sRearFarRadius, draw_distance);
  483. LL_DEBUGS("ObjectCache") << "Rear far radius = " << sRearFarRadius << "m."
  484. << LL_ENDL;
  485. }
  486. //static
  487. F32 LLVOCacheEntry::getSquaredPixelThreshold(bool is_front)
  488. {
  489. F32 threshold;
  490. if (is_front)
  491. {
  492. threshold = sFrontPixelThreshold;
  493. }
  494. else
  495. {
  496. threshold = sRearPixelThreshold;
  497. }
  498. // Object projected area threshold
  499. F32 pixel_meter_ratio = gViewerCamera.getPixelMeterRatio();
  500. F32 projection_threshold =
  501. pixel_meter_ratio > 0.f ? threshold / pixel_meter_ratio : 0.f;
  502. return projection_threshold * projection_threshold;
  503. }
  504. bool LLVOCacheEntry::isAnyVisible(const LLVector4a& camera_origin,
  505. const LLVector4a& local_camera_origin,
  506. F32 dist_threshold)
  507. {
  508. static LLCachedControl<bool> use_visibility(gSavedSettings,
  509. "UseObjectCacheVisibility");
  510. if (!use_visibility)
  511. {
  512. return true;
  513. }
  514. LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)getGroup();
  515. if (!group)
  516. {
  517. return false;
  518. }
  519. // Any visible
  520. bool vis = group->isAnyRecentlyVisible();
  521. if (!vis) // Not ready to remove
  522. {
  523. S32 cur_vis = llmax(group->getAnyVisible(), (S32)getVisible());
  524. #if HB_AJUSTED_VOCACHE_PARAMETERS
  525. // Adjust the delta based on the actual frame rate so that it
  526. // translates into seconds.
  527. F32 fps_ratio_to_target = F32_MAX;
  528. if (gFrameIntervalSeconds > 0.f)
  529. {
  530. fps_ratio_to_target = FRAME_MS_TARGET / gFrameIntervalSeconds;
  531. }
  532. S32 delta = (S32)((F32)sMinFrameRange * fps_ratio_to_target);
  533. if (sBiasedRetention)
  534. {
  535. // Adjust the delta time depending on the discard bias (the higher
  536. // the latter, the lower the former). This means that we release
  537. // the non-visible objects sooner when the memory consumption gets
  538. // higher.
  539. delta = (S32)((F32)delta /
  540. (LLViewerTexture::sDesiredDiscardBias + 1.f));
  541. }
  542. #else
  543. S32 delta = sMinFrameRange;
  544. #endif
  545. vis = cur_vis + delta > LLViewerOctreeEntryData::getCurrentFrame();
  546. }
  547. // Within the back sphere
  548. if (!vis && !mParentID &&
  549. !group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
  550. {
  551. LLVector4a look_at;
  552. if (mBSphereRadius > 0.f)
  553. {
  554. look_at.setSub(mBSphereCenter, local_camera_origin);
  555. dist_threshold += mBSphereRadius;
  556. }
  557. else
  558. {
  559. look_at.setSub(getPositionGroup(), camera_origin);
  560. dist_threshold += getBinRadius();
  561. }
  562. vis = look_at.dot3(look_at).getF32() < dist_threshold * dist_threshold;
  563. }
  564. return vis;
  565. }
  566. void LLVOCacheEntry::calcSceneContribution(const LLVector4a& camera_origin,
  567. bool needs_update, U32 last_update,
  568. F32 max_dist)
  569. {
  570. if (!needs_update && getVisible() >= last_update)
  571. {
  572. return; // no need to update
  573. }
  574. LLVector4a look_at;
  575. look_at.setSub(getPositionGroup(), camera_origin);
  576. F32 near_radius = sNearRadius;
  577. #if HB_AJUSTED_VOCACHE_PARAMETERS
  578. if (sBiasedRetention)
  579. {
  580. near_radius /= LLViewerTexture::sDesiredDiscardBias / 3.f + 1.f;
  581. }
  582. #endif
  583. F32 distance = look_at.getLength3().getF32() - near_radius;
  584. if (distance <= 0.f)
  585. {
  586. // Nearby objects, set a large number to force to load the object.
  587. constexpr F32 LARGE_SCENE_CONTRIBUTION = 1000.f;
  588. mSceneContrib = LARGE_SCENE_CONTRIBUTION;
  589. }
  590. else
  591. {
  592. F32 rad = getBinRadius();
  593. max_dist += rad;
  594. if (distance + near_radius < max_dist)
  595. {
  596. mSceneContrib = rad * rad / distance;
  597. }
  598. else
  599. {
  600. mSceneContrib = 0.f; // out of draw distance, not to load
  601. }
  602. }
  603. setVisible();
  604. }
  605. void LLVOCacheEntry::saveBoundingSphere()
  606. {
  607. mBSphereCenter = getPositionGroup();
  608. mBSphereRadius = getBinRadius();
  609. }
  610. void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos,
  611. const LLVector3& scale)
  612. {
  613. LLVector4a center, new_min, new_max;
  614. center.load3(pos.mV);
  615. LLVector4a size;
  616. size.load3(scale.mV);
  617. new_min.setSub(center, size);
  618. new_max.setAdd(center, size);
  619. setPositionGroup(center);
  620. setSpatialExtents(new_min, new_max);
  621. if (getNumOfChildren() > 0) // has children
  622. {
  623. updateParentBoundingInfo();
  624. }
  625. else
  626. {
  627. setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f));
  628. }
  629. }
  630. // Make the parent bounding box to include all children
  631. void LLVOCacheEntry::updateParentBoundingInfo()
  632. {
  633. if (mChildrenList.empty())
  634. {
  635. return;
  636. }
  637. for (set_t::iterator iter = mChildrenList.begin(),
  638. end = mChildrenList.end();
  639. iter != end; ++iter)
  640. {
  641. updateParentBoundingInfo(*iter);
  642. }
  643. resetVisible();
  644. }
  645. // Make the parent bounding box to include this child
  646. void LLVOCacheEntry::updateParentBoundingInfo(const LLVOCacheEntry* child)
  647. {
  648. const LLVector4a* child_exts = child->getSpatialExtents();
  649. LLVector4a new_min, new_max;
  650. new_min = child_exts[0];
  651. new_max = child_exts[1];
  652. // Move to regional space.
  653. const LLVector4a& parent_pos = getPositionGroup();
  654. new_min.add(parent_pos);
  655. new_max.add(parent_pos);
  656. // Update parent's bbox(min, max)
  657. const LLVector4a* parent_exts = getSpatialExtents();
  658. update_min_max(new_min, new_max, parent_exts[0]);
  659. update_min_max(new_min, new_max, parent_exts[1]);
  660. // Clamping
  661. static const LLVector4a min_vector(-65536.f);
  662. static const LLVector4a max_vector(65536.f);
  663. new_min.clamp(min_vector, max_vector);
  664. new_max.clamp(min_vector, max_vector);
  665. setSpatialExtents(new_min, new_max);
  666. // Update parent's bbox center
  667. LLVector4a center;
  668. center.setAdd(new_min, new_max);
  669. center.mul(0.5f);
  670. setPositionGroup(center);
  671. // Update parent's bbox size vector
  672. LLVector4a size;
  673. size.setSub(new_max, new_min);
  674. size.mul(0.5f);
  675. setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f));
  676. }
  677. //-------------------------------------------------------------------
  678. // LLVOCacheGroup
  679. //-------------------------------------------------------------------
  680. LLVOCacheGroup::~LLVOCacheGroup()
  681. {
  682. if (mOcclusionState[LLViewerCamera::CAMERA_WORLD] & ACTIVE_OCCLUSION)
  683. {
  684. ((LLVOCachePartition*)mSpatialPartition)->removeOccluder(this);
  685. }
  686. }
  687. //virtual
  688. void LLVOCacheGroup::handleChildAddition(const OctreeNode* parent,
  689. OctreeNode* child)
  690. {
  691. if (child->getListenerCount() == 0)
  692. {
  693. new LLVOCacheGroup(child, mSpatialPartition);
  694. }
  695. else
  696. {
  697. llwarns << "Redundancy detected." << llendl;
  698. llassert(false);
  699. }
  700. unbound();
  701. ((LLViewerOctreeGroup*)child->getListener(0))->unbound();
  702. }
  703. //-------------------------------------------------------------------
  704. // LLVOCachePartition
  705. //-------------------------------------------------------------------
  706. LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp)
  707. {
  708. mLODPeriod = 16;
  709. mRegionp = regionp;
  710. mPartitionType = LLViewerRegion::PARTITION_VO_CACHE;
  711. mBackSlectionEnabled = -1;
  712. mIdleHash = 0;
  713. for (S32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
  714. {
  715. mCulledTime[i] = 0;
  716. }
  717. mCullHistory = -1;
  718. new LLVOCacheGroup(mOctree, this);
  719. }
  720. LLVOCachePartition::~LLVOCachePartition()
  721. {
  722. // SL-17276 make sure to do base class cleanup while this instance can
  723. // can still be treated as an LLVOCachePartition.
  724. cleanup();
  725. }
  726. bool LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry)
  727. {
  728. llassert(entry->hasVOCacheEntry());
  729. if (!llfinite(entry->getBinRadius()) ||
  730. !entry->getPositionGroup().isFinite3())
  731. {
  732. return false; // data is corrupted
  733. }
  734. mOctree->insert(entry);
  735. return true;
  736. }
  737. void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry)
  738. {
  739. entry->getVOCacheEntry()->setGroup(NULL);
  740. llassert(!entry->getGroup());
  741. }
  742. class LLVOCacheOctreeCull final : public LLViewerOctreeCull
  743. {
  744. public:
  745. LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp,
  746. const LLVector3& shift, bool use_cache_occlusion,
  747. F32 pixel_threshold, F32 near_radius,
  748. LLVOCachePartition* part)
  749. : LLViewerOctreeCull(camera),
  750. mRegionp(regionp),
  751. mUseObjectCacheOcclusion(use_cache_occlusion),
  752. mPixelThreshold(pixel_threshold),
  753. mNearRadius(near_radius),
  754. mPartition(part)
  755. {
  756. mLocalShift = shift;
  757. }
  758. bool earlyFail(LLViewerOctreeGroup* base_group) override
  759. {
  760. if (mUseObjectCacheOcclusion &&
  761. // never occlusion-cull the root node
  762. base_group->getOctreeNode()->getParent())
  763. {
  764. LLOcclusionCullingGroup* group =
  765. (LLOcclusionCullingGroup*)base_group;
  766. if (group->needsUpdate())
  767. {
  768. // Needs to issue new occlusion culling check, perform view
  769. // culling check first.
  770. return false;
  771. }
  772. group->checkOcclusion();
  773. if (group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
  774. {
  775. return true;
  776. }
  777. }
  778. return false;
  779. }
  780. S32 frustumCheck(const LLViewerOctreeGroup* group) override
  781. {
  782. #if 0
  783. S32 res = AABBInRegionFrustumGroupBounds(group);
  784. #else
  785. S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group);
  786. if (res != 0)
  787. {
  788. res = llmin(res,
  789. AABBRegionSphereIntersectGroupExtents(group,
  790. mLocalShift));
  791. }
  792. #endif
  793. return res;
  794. }
  795. S32 frustumCheckObjects(const LLViewerOctreeGroup* group) override
  796. {
  797. #if 0
  798. S32 res = AABBInRegionFrustumObjectBounds(group);
  799. #else
  800. S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group);
  801. if (res != 0)
  802. {
  803. res = llmin(res,
  804. AABBRegionSphereIntersectObjectExtents(group,
  805. mLocalShift));
  806. }
  807. #endif
  808. if (res != 0)
  809. {
  810. // Check if the objects projection large enough
  811. const LLVector4a* exts = group->getObjectExtents();
  812. res = checkProjectionArea(exts[0], exts[1], mLocalShift,
  813. mPixelThreshold, mNearRadius);
  814. }
  815. return res;
  816. }
  817. void processGroup(LLViewerOctreeGroup* base_group) override
  818. {
  819. if (!mUseObjectCacheOcclusion ||
  820. !base_group->getOctreeNode()->getParent())
  821. {
  822. // No occlusion check
  823. if (mRegionp->addVisibleGroup(base_group))
  824. {
  825. base_group->setVisible();
  826. }
  827. return;
  828. }
  829. LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group;
  830. if (group->needsUpdate() || !group->isRecentlyVisible())
  831. {
  832. // Needs to issue new occlusion culling check.
  833. mPartition->addOccluders(group);
  834. group->setVisible();
  835. return ; // wait for occlusion culling result
  836. }
  837. if (group->isOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING) ||
  838. group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION))
  839. {
  840. // Keep waiting
  841. group->setVisible();
  842. }
  843. else if (mRegionp->addVisibleGroup(base_group))
  844. {
  845. base_group->setVisible();
  846. }
  847. }
  848. private:
  849. LLVOCachePartition* mPartition;
  850. LLViewerRegion* mRegionp;
  851. // Shift vector from agent space to local region space:
  852. LLVector3 mLocalShift;
  853. F32 mPixelThreshold;
  854. F32 mNearRadius;
  855. bool mUseObjectCacheOcclusion;
  856. };
  857. // Select objects behind camera
  858. class LLVOCacheOctreeBackCull final : public LLViewerOctreeCull
  859. {
  860. public:
  861. LL_INLINE LLVOCacheOctreeBackCull(LLCamera* camera, const LLVector3& shift,
  862. LLViewerRegion* regionp, F32 threshold,
  863. F32 radius, bool use_occlusion)
  864. : LLViewerOctreeCull(camera),
  865. mRegionp(regionp),
  866. mPixelThreshold(threshold),
  867. mSphereRadius(radius),
  868. mUseObjectCacheOcclusion(use_occlusion)
  869. {
  870. mLocalShift = shift;
  871. }
  872. bool earlyFail(LLViewerOctreeGroup* base_group) override
  873. {
  874. if (mUseObjectCacheOcclusion &&
  875. // Never occlusion-cull the root node
  876. base_group->getOctreeNode()->getParent())
  877. {
  878. LLOcclusionCullingGroup* group =
  879. (LLOcclusionCullingGroup*)base_group;
  880. if (group->getOcclusionState() > 0)
  881. {
  882. // Occlusion state is not clear.
  883. return true;
  884. }
  885. }
  886. return false;
  887. }
  888. LL_INLINE S32 frustumCheck(const LLViewerOctreeGroup* group) override
  889. {
  890. const LLVector4a* exts = group->getExtents();
  891. return backSphereCheck(exts[0], exts[1]);
  892. }
  893. S32 frustumCheckObjects(const LLViewerOctreeGroup* group) override
  894. {
  895. const LLVector4a* exts = group->getObjectExtents();
  896. if (backSphereCheck(exts[0], exts[1]))
  897. {
  898. // Check if the objects projection large enough
  899. const LLVector4a* exts = group->getObjectExtents();
  900. return checkProjectionArea(exts[0], exts[1],
  901. mLocalShift, mPixelThreshold,
  902. mSphereRadius);
  903. }
  904. return false;
  905. }
  906. LL_INLINE void processGroup(LLViewerOctreeGroup* base_group) override
  907. {
  908. mRegionp->addVisibleGroup(base_group);
  909. }
  910. private:
  911. // A sphere around the camera origin, including objects behind camera.
  912. LL_INLINE S32 backSphereCheck(const LLVector4a& min, const LLVector4a& max)
  913. {
  914. return AABBSphereIntersect(min, max,
  915. mCamera->getOrigin() - mLocalShift,
  916. mSphereRadius);
  917. }
  918. private:
  919. F32 mSphereRadius;
  920. LLViewerRegion* mRegionp;
  921. // shift vector from agent space to local region space.
  922. LLVector3 mLocalShift;
  923. F32 mPixelThreshold;
  924. bool mUseObjectCacheOcclusion;
  925. };
  926. void LLVOCachePartition::selectBackObjects(LLCamera& camera,
  927. F32 pixel_threshold,
  928. bool use_occlusion)
  929. {
  930. if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
  931. {
  932. return;
  933. }
  934. if (mBackSlectionEnabled < 0)
  935. {
  936. mBackSlectionEnabled = LLVOCacheEntry::sMinFrameRange - 1;
  937. mBackSlectionEnabled = llmax(mBackSlectionEnabled, (S32)1);
  938. }
  939. if (!mBackSlectionEnabled)
  940. {
  941. return;
  942. }
  943. // Localize the camera
  944. LLVector3 region_agent = mRegionp->getOriginAgent();
  945. F32 radius = LLVOCacheEntry::sRearFarRadius;
  946. #if HB_AJUSTED_VOCACHE_PARAMETERS
  947. if (LLVOCacheEntry::sBiasedRetention)
  948. {
  949. radius /= LLViewerTexture::sDesiredDiscardBias / 3.f + 1.f;
  950. }
  951. #endif
  952. LLVOCacheOctreeBackCull culler(&camera, region_agent, mRegionp,
  953. pixel_threshold, radius, use_occlusion);
  954. culler.traverse(mOctree);
  955. if (mRegionp->getNumOfVisibleGroups())
  956. {
  957. --mBackSlectionEnabled;
  958. }
  959. else
  960. {
  961. mBackSlectionEnabled = 0;
  962. }
  963. }
  964. S32 LLVOCachePartition::cull(LLCamera& camera, bool do_occlusion)
  965. {
  966. LL_FAST_TIMER(FTM_CULL_VOCACHE);
  967. static LLCachedControl<bool> use_cache_occlusion(gSavedSettings,
  968. "UseObjectCacheOcclusion");
  969. if (!use_cache_occlusion)
  970. {
  971. do_occlusion = false;
  972. }
  973. if (!LLViewerRegion::sVOCacheCullingEnabled || mRegionp->isPaused())
  974. {
  975. return 0;
  976. }
  977. ((LLViewerOctreeGroup*)mOctree->getListener(0))->rebound();
  978. if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
  979. {
  980. // No need for those cameras.
  981. return 0;
  982. }
  983. S32 frame = LLViewerOctreeEntryData::getCurrentFrame();
  984. if ((S32)mCulledTime[LLViewerCamera::sCurCameraID] == frame)
  985. {
  986. return 0; // Already culled
  987. }
  988. mCulledTime[LLViewerCamera::sCurCameraID] = frame;
  989. if (!mCullHistory && LLViewerRegion::isViewerCameraStatic())
  990. {
  991. U32 seed = llmax(mLODPeriod >> 1, 4U);
  992. if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
  993. {
  994. if (frame % seed == 0)
  995. {
  996. mIdleHash = (mIdleHash + 1) % seed;
  997. }
  998. }
  999. if (frame % seed != mIdleHash)
  1000. {
  1001. mFrontCull = false;
  1002. // Process back objects selection
  1003. selectBackObjects(camera,
  1004. LLVOCacheEntry::getSquaredPixelThreshold(mFrontCull),
  1005. do_occlusion);
  1006. return 0; // Nothing changed, reduce frequency of culling
  1007. }
  1008. }
  1009. else
  1010. {
  1011. mBackSlectionEnabled = -1; // Reset it.
  1012. }
  1013. // Localize the camera
  1014. LLVector3 region_agent = mRegionp->getOriginAgent();
  1015. camera.calcRegionFrustumPlanes(region_agent, gAgent.mDrawDistance);
  1016. mFrontCull = true;
  1017. F32 near_radius = LLVOCacheEntry::sNearRadius;
  1018. #if HB_AJUSTED_VOCACHE_PARAMETERS
  1019. if (LLVOCacheEntry::sBiasedRetention)
  1020. {
  1021. near_radius /= LLViewerTexture::sDesiredDiscardBias / 3.f + 1.f;
  1022. }
  1023. #endif
  1024. LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent,
  1025. do_occlusion,
  1026. LLVOCacheEntry::getSquaredPixelThreshold(mFrontCull),
  1027. near_radius, this);
  1028. culler.traverse(mOctree);
  1029. if (!sNeedsOcclusionCheck)
  1030. {
  1031. sNeedsOcclusionCheck = !mOccludedGroups.empty();
  1032. }
  1033. return 1;
  1034. }
  1035. void LLVOCachePartition::setCullHistory(bool has_new_object)
  1036. {
  1037. mCullHistory <<= 1;
  1038. mCullHistory |= has_new_object ? 1 : 0;
  1039. }
  1040. void LLVOCachePartition::addOccluders(LLViewerOctreeGroup* gp)
  1041. {
  1042. LLVOCacheGroup* group = (LLVOCacheGroup*)gp;
  1043. if (!group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION))
  1044. {
  1045. group->setOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
  1046. mOccludedGroups.insert(group);
  1047. }
  1048. }
  1049. void LLVOCachePartition::processOccluders(LLCamera* camera)
  1050. {
  1051. if (mOccludedGroups.empty() ||
  1052. // No need for those cameras
  1053. LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
  1054. {
  1055. return;
  1056. }
  1057. LLVector3 region_agent = mRegionp->getOriginAgent();
  1058. LLVector4a shift(region_agent[0], region_agent[1], region_agent[2]);
  1059. for (std::set<LLVOCacheGroup*>::iterator iter = mOccludedGroups.begin(),
  1060. end = mOccludedGroups.end();
  1061. iter != end; ++iter)
  1062. {
  1063. LLVOCacheGroup* group = *iter;
  1064. if (group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION))
  1065. {
  1066. group->doOcclusion(camera, &shift);
  1067. group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
  1068. }
  1069. }
  1070. // Safe to clear mOccludedGroups here because only the world camera
  1071. // accesses it.
  1072. mOccludedGroups.clear();
  1073. sNeedsOcclusionCheck = false;
  1074. }
  1075. void LLVOCachePartition::resetOccluders()
  1076. {
  1077. if (mOccludedGroups.empty())
  1078. {
  1079. return;
  1080. }
  1081. for (std::set<LLVOCacheGroup*>::iterator
  1082. iter = mOccludedGroups.begin(), end = mOccludedGroups.end();
  1083. iter != end; ++iter)
  1084. {
  1085. LLVOCacheGroup* group = *iter;
  1086. group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
  1087. }
  1088. mOccludedGroups.clear();
  1089. sNeedsOcclusionCheck = false;
  1090. }
  1091. void LLVOCachePartition::removeOccluder(LLVOCacheGroup* groupp)
  1092. {
  1093. if (!mOccludedGroups.empty())
  1094. {
  1095. mOccludedGroups.erase(groupp);
  1096. }
  1097. }
  1098. ///////////////////////////////////////////////////////////////////////////////
  1099. // LLVOCache
  1100. ///////////////////////////////////////////////////////////////////////////////
  1101. // Format string used to construct filename for the object cache
  1102. static const char* OBJECT_CACHE_FILENAME = "%sobjects_%d_%d.slc";
  1103. static const char* OBJECT_CACHE_EXTRAS_FILENAME = "%sobjects_%d_%d_extras.slc";
  1104. static const char* HEADER_FILENAME = "%sobject.cache";
  1105. static const char* OBJECT_CACHE_DIRNAME = "objectcache";
  1106. constexpr U32 MAX_NUM_OBJECT_ENTRIES = 128;
  1107. constexpr U32 MIN_ENTRIES_TO_PURGE = 16;
  1108. constexpr U32 INVALID_TIME = 0;
  1109. LLVOCache::LLVOCache()
  1110. : mInitialized(false),
  1111. mReadOnly(true),
  1112. mNumEntries(0),
  1113. mCacheSize(1)
  1114. {
  1115. mEnabled = gSavedSettings.getBool("ObjectDiskCacheEnabled");
  1116. if (mEnabled)
  1117. {
  1118. llinfos << "Initializing with 1 worker thread." << llendl;
  1119. mThreadPoolp.reset(new LLThreadPool("Object cache", 1));
  1120. mThreadPoolp->start();
  1121. }
  1122. llinfos << "Objects cache created." << llendl;
  1123. }
  1124. LLVOCache::~LLVOCache()
  1125. {
  1126. if (mThreadPoolp)
  1127. {
  1128. mThreadPoolp->close();
  1129. mThreadPoolp.reset(nullptr);
  1130. llinfos << "Thread pool destroyed." << llendl;
  1131. }
  1132. if (mEnabled)
  1133. {
  1134. writeCacheHeader();
  1135. clearCacheInMemory();
  1136. }
  1137. llinfos << "Objects cache destroyed." << llendl;
  1138. }
  1139. void LLVOCache::setDirNames(ELLPath location)
  1140. {
  1141. std::string grid;
  1142. if (!gIsInSecondLife)
  1143. {
  1144. LLGridManager* gridmgrp = LLGridManager::getInstance();
  1145. grid = LLDir::getScrubbedFileName(gridmgrp->getGridLabel()) + "_";
  1146. }
  1147. else if (!gIsInSecondLifeProductionGrid)
  1148. {
  1149. grid = "beta_";
  1150. }
  1151. mHeaderFileName = gDirUtil.getFullPath(location, OBJECT_CACHE_DIRNAME,
  1152. llformat(HEADER_FILENAME,
  1153. grid.c_str()));
  1154. mObjectCacheDirName = gDirUtil.getFullPath(location, OBJECT_CACHE_DIRNAME);
  1155. }
  1156. void LLVOCache::initCache(ELLPath location, U32 size)
  1157. {
  1158. if (!mEnabled)
  1159. {
  1160. llinfos << "Not initializing cache: cache is currently disabled."
  1161. << llendl;
  1162. return;
  1163. }
  1164. if (mInitialized)
  1165. {
  1166. llwarns << "Cache already initialized." << llendl;
  1167. return;
  1168. }
  1169. mInitialized = true;
  1170. setDirNames(location);
  1171. if (!mReadOnly)
  1172. {
  1173. LLFile::mkdir(mObjectCacheDirName);
  1174. }
  1175. mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES);
  1176. readCacheHeader();
  1177. if (mMetaInfo.mVersion != OBJECT_CACHE_VERSION ||
  1178. mMetaInfo.mAddressSize != ADDRESS_SIZE)
  1179. {
  1180. mMetaInfo.mVersion = OBJECT_CACHE_VERSION;
  1181. mMetaInfo.mAddressSize = ADDRESS_SIZE;
  1182. if (mReadOnly) // Disable cache
  1183. {
  1184. clearCacheInMemory();
  1185. }
  1186. else // Delete the current cache if the format does not match.
  1187. {
  1188. removeCache();
  1189. }
  1190. }
  1191. llinfos << "Cache initialized in directory: " << mObjectCacheDirName
  1192. << " - with cache header file name: " << mHeaderFileName
  1193. << " - cache in read" << (mReadOnly ? " only" : "-write")
  1194. << " mode." << llendl;
  1195. }
  1196. void LLVOCache::removeCache(ELLPath location)
  1197. {
  1198. if (mReadOnly)
  1199. {
  1200. llinfos << "Not removing cache at " << location
  1201. << ": cache is currently in read-only mode." << llendl;
  1202. return;
  1203. }
  1204. llinfos << "About to remove the object cache due to settings." << llendl;
  1205. std::string cache_dir = gDirUtil.getFullPath(location,
  1206. OBJECT_CACHE_DIRNAME);
  1207. llinfos << "Removing object cache at " << cache_dir << llendl;
  1208. LLDirIterator::deleteFilesInDir(cache_dir); // Delete all files
  1209. LLFile::rmdir(cache_dir);
  1210. clearCacheInMemory();
  1211. mInitialized = false;
  1212. }
  1213. void LLVOCache::removeCache()
  1214. {
  1215. if (mReadOnly)
  1216. {
  1217. llinfos << "Not clearing object cache which is currently in read-only mode."
  1218. << llendl;
  1219. return;
  1220. }
  1221. if (!mInitialized)
  1222. {
  1223. // OK to remove cache even it is not initialized.
  1224. llwarns << "Object cache is not initialized yet." << llendl;
  1225. }
  1226. llinfos << "Removing object cache at " << mObjectCacheDirName << llendl;
  1227. LLDirIterator::deleteFilesInDir(mObjectCacheDirName);
  1228. clearCacheInMemory();
  1229. writeCacheHeader();
  1230. }
  1231. // Note: may be occasionnally called (indirectly, via removeEntry(U64 handle)
  1232. // below) from the cache workers, whenever a bad cache entry is found or the
  1233. // cache file cannot be read or written. HB
  1234. void LLVOCache::removeEntry(HeaderEntryInfo* entry)
  1235. {
  1236. mMutex.lock(); // See above as for why we need a mutex here... HB
  1237. if (entry && mInitialized && !mReadOnly)
  1238. {
  1239. header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry);
  1240. if (iter != mHeaderEntryQueue.end())
  1241. {
  1242. mHandleEntryMap.erase(entry->mHandle);
  1243. mHeaderEntryQueue.erase(iter);
  1244. removeFromCache(entry);
  1245. delete entry;
  1246. mNumEntries = mHandleEntryMap.size();
  1247. }
  1248. }
  1249. mMutex.unlock();
  1250. }
  1251. // Note: may be occasionnally called from the cache workers, whenever a bad
  1252. // cache entry is found or the cache file cannot be read or written. HB
  1253. void LLVOCache::removeEntry(U64 handle)
  1254. {
  1255. mMutex.lock(); // See above as for why we need a mutex here... HB
  1256. handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle);
  1257. if (iter != mHandleEntryMap.end())
  1258. {
  1259. // Note: mMutex will again be locked, but it is OK since LLMutex
  1260. // is recursive. HB
  1261. removeEntry(iter->second);
  1262. }
  1263. mMutex.unlock();
  1264. }
  1265. void LLVOCache::clearCacheInMemory()
  1266. {
  1267. if (!mHeaderEntryQueue.empty())
  1268. {
  1269. for (header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(),
  1270. end = mHeaderEntryQueue.end();
  1271. iter != end; ++iter)
  1272. {
  1273. delete *iter;
  1274. }
  1275. mHeaderEntryQueue.clear();
  1276. mHandleEntryMap.clear();
  1277. mNumEntries = 0;
  1278. }
  1279. }
  1280. void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename,
  1281. bool extra_entries)
  1282. {
  1283. std::string grid;
  1284. if (!gIsInSecondLife)
  1285. {
  1286. LLGridManager* gridmgrp = LLGridManager::getInstance();
  1287. grid = LLDir::getScrubbedFileName(gridmgrp->getGridLabel()) + "_";
  1288. }
  1289. else if (!gIsInSecondLifeProductionGrid)
  1290. {
  1291. grid = "beta_";
  1292. }
  1293. U32 region_x, region_y;
  1294. grid_from_region_handle(handle, &region_x, &region_y);
  1295. const char* name_format = extra_entries ? OBJECT_CACHE_EXTRAS_FILENAME
  1296. : OBJECT_CACHE_FILENAME;
  1297. filename = gDirUtil.getFullPath(LL_PATH_CACHE, OBJECT_CACHE_DIRNAME,
  1298. llformat(name_format, grid.c_str(),
  1299. region_x, region_y));
  1300. }
  1301. void LLVOCache::removeFromCache(HeaderEntryInfo* entry)
  1302. {
  1303. if (mReadOnly)
  1304. {
  1305. llinfos << "Not removing cache for handle " << entry->mHandle
  1306. << ": cache is currently in read-only mode." << llendl;
  1307. return;
  1308. }
  1309. std::string filename;
  1310. getObjectCacheFilename(entry->mHandle, filename);
  1311. LLFile::remove(filename);
  1312. entry->mTime = INVALID_TIME;
  1313. updateEntry(entry); // Update the head file.
  1314. }
  1315. void LLVOCache::readCacheHeader()
  1316. {
  1317. // Initialize meta info, in case there is no cache to read
  1318. mMetaInfo.mVersion = OBJECT_CACHE_VERSION;
  1319. mMetaInfo.mAddressSize = ADDRESS_SIZE;
  1320. if (!mEnabled)
  1321. {
  1322. LL_DEBUGS("ObjectCache") << "Not reading cache header: cache is currently disabled."
  1323. << LL_ENDL;
  1324. return;
  1325. }
  1326. // Clear stale info.
  1327. clearCacheInMemory();
  1328. bool success = true;
  1329. if (LLFile::exists(mHeaderFileName))
  1330. {
  1331. LLFile infile(mHeaderFileName, "rb");
  1332. // Read the meta element
  1333. success = check_read(&infile, (U8*)&mMetaInfo, sizeof(HeaderMetaInfo));
  1334. if (success)
  1335. {
  1336. HeaderEntryInfo* entry = NULL;
  1337. mNumEntries = 0;
  1338. U32 num_read = 0;
  1339. while (num_read++ < MAX_NUM_OBJECT_ENTRIES)
  1340. {
  1341. if (!entry)
  1342. {
  1343. entry = new HeaderEntryInfo();
  1344. }
  1345. success = check_read(&infile, (U8*)entry,
  1346. sizeof(HeaderEntryInfo));
  1347. if (!success)
  1348. {
  1349. llwarns << "Error reading cache header entry. (entry_index="
  1350. << mNumEntries << ")" << llendl;
  1351. delete entry;
  1352. entry = NULL;
  1353. break;
  1354. }
  1355. if (entry->mTime == INVALID_TIME)
  1356. {
  1357. continue; // An empty entry
  1358. }
  1359. entry->mIndex = mNumEntries++;
  1360. mHeaderEntryQueue.insert(entry);
  1361. mHandleEntryMap[entry->mHandle] = entry;
  1362. entry = NULL;
  1363. }
  1364. if (entry)
  1365. {
  1366. delete entry;
  1367. }
  1368. }
  1369. }
  1370. else
  1371. {
  1372. writeCacheHeader();
  1373. }
  1374. if (success && mNumEntries >= mCacheSize)
  1375. {
  1376. purgeEntries(mCacheSize);
  1377. }
  1378. }
  1379. void LLVOCache::writeCacheHeader()
  1380. {
  1381. if (mReadOnly || !mEnabled)
  1382. {
  1383. LL_DEBUGS("ObjectCache") << "Not writing cache header: cache is currently "
  1384. << (mEnabled ? "disabled." : "in read-only mode.")
  1385. << LL_ENDL;
  1386. return;
  1387. }
  1388. bool success = true;
  1389. {
  1390. // Write the header file. Note that we are using "wb" (which overwrites
  1391. // any existing file; this is essential to avoid writing a smaller
  1392. // amount of data in a larger file, which would result in a "corrupted"
  1393. // error on next read to EOF). HB
  1394. LLFile outfile(mHeaderFileName, "wb");
  1395. // Write the meta element
  1396. success = check_write(&outfile, (U8*)&mMetaInfo,
  1397. sizeof(HeaderMetaInfo));
  1398. mNumEntries = 0;
  1399. for (header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(),
  1400. end = mHeaderEntryQueue.end();
  1401. success && iter != end; ++iter)
  1402. {
  1403. (*iter)->mIndex = mNumEntries++;
  1404. success = check_write(&outfile, (U8*)*iter,
  1405. sizeof(HeaderEntryInfo));
  1406. }
  1407. mNumEntries = mHeaderEntryQueue.size();
  1408. if (success && mNumEntries < MAX_NUM_OBJECT_ENTRIES)
  1409. {
  1410. HeaderEntryInfo* entry = new HeaderEntryInfo();
  1411. entry->mTime = INVALID_TIME;
  1412. for (S32 i = mNumEntries;
  1413. success && i < (S32)MAX_NUM_OBJECT_ENTRIES; ++i)
  1414. {
  1415. // Fill the cache with the default entry.
  1416. success = check_write(&outfile, (U8*)entry,
  1417. sizeof(HeaderEntryInfo));
  1418. }
  1419. delete entry;
  1420. }
  1421. }
  1422. if (!success)
  1423. {
  1424. clearCacheInMemory();
  1425. mReadOnly = true; // Disable the cache on failure to write it.
  1426. }
  1427. }
  1428. bool LLVOCache::updateEntry(const HeaderEntryInfo* entry)
  1429. {
  1430. // NOT using "wb" here, since we seek to an entry to update it.
  1431. LLFile outfile(mHeaderFileName, "r+b");
  1432. S64 offset = entry->mIndex * sizeof(HeaderEntryInfo) +
  1433. sizeof(HeaderMetaInfo);
  1434. if (outfile.seek(offset) != offset)
  1435. {
  1436. llwarns << "Failed to seek to entry index " << entry->mIndex << llendl;
  1437. return false;
  1438. }
  1439. if (!check_write(&outfile, (U8*)entry, sizeof(HeaderEntryInfo)))
  1440. {
  1441. llwarns << "Failed to write entry at index " << entry->mIndex
  1442. << llendl;
  1443. return false;
  1444. }
  1445. return outfile.flush();
  1446. }
  1447. void LLVOCache::readFromCache(U64 handle, const std::string& region_name,
  1448. const LLUUID& id)
  1449. {
  1450. LL_TRACY_TIMER(TRC_OBJ_CACHE_READ);
  1451. static LLCachedControl<bool> allow_read(gSavedSettings,
  1452. "ObjectDiskCacheReads");
  1453. if (!mEnabled || !allow_read)
  1454. {
  1455. LLViewerRegion::cacheLoadedCallback(handle, NULL, NULL);
  1456. return;
  1457. }
  1458. if (!mInitialized)
  1459. {
  1460. llwarns << "Call done while not initialized !" << llendl;
  1461. llassert(false);
  1462. LLViewerRegion::cacheLoadedCallback(handle, NULL, NULL);
  1463. return;
  1464. }
  1465. LLTimer read_timer;
  1466. read_timer.reset();
  1467. handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle);
  1468. if (iter == mHandleEntryMap.end()) // No cache
  1469. {
  1470. llinfos << "Cache miss for region: " << region_name << llendl;
  1471. LLViewerRegion::cacheLoadedCallback(handle, NULL, NULL);
  1472. return;
  1473. }
  1474. static LLCachedControl<bool> use_thread_pool(gSavedSettings,
  1475. "ThreadedObjectCacheReads");
  1476. // Note: cannot queue when shutting down (it would crash). HB
  1477. if (!use_thread_pool || LLApp::isExiting() || !mThreadPoolp)
  1478. {
  1479. ReadWorker worker(handle, id, region_name);
  1480. worker.readCacheFile();
  1481. llinfos << "Object cache read for region '" << region_name << "' in "
  1482. << read_timer.getElapsedTimeF32() * 1000.f << "ms." << llendl;
  1483. return;
  1484. }
  1485. std::string filename;
  1486. getObjectCacheFilename(handle, filename);
  1487. if (!LLFile::exists(filename))
  1488. {
  1489. llwarns << "Could not find: " << filename << " - Region: "
  1490. << region_name << ". Removing entry." << llendl;
  1491. removeEntry(iter->second);
  1492. return;
  1493. }
  1494. // Queue the cache file read
  1495. mThreadPoolp->getQueue().post(
  1496. [worker = ReadWorker(handle, id, region_name)]() mutable
  1497. {
  1498. LL_TRACY_TIMER(TRC_OBJ_CACHE_THREAD_READ);
  1499. // Queued reads are aborted on shutdown to prevent crashes (because
  1500. // LLThreadPool did already shut down on LLApp::isExiting()); this
  1501. // it not a problem at all (too late to rez objects). HB
  1502. if (!LLApp::isExiting())
  1503. {
  1504. worker.readCacheFile();
  1505. }
  1506. });
  1507. llinfos << "Queued cache read operation for region '" << region_name
  1508. << "' in " << read_timer.getElapsedTimeF32() * 1000.f << "ms."
  1509. << llendl;
  1510. }
  1511. void LLVOCache::purgeEntries(U32 size)
  1512. {
  1513. while (mHeaderEntryQueue.size() > size)
  1514. {
  1515. header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin();
  1516. HeaderEntryInfo* entry = *iter;
  1517. mHandleEntryMap.erase(entry->mHandle);
  1518. mHeaderEntryQueue.erase(iter);
  1519. removeFromCache(entry);
  1520. delete entry;
  1521. }
  1522. mNumEntries = mHandleEntryMap.size();
  1523. }
  1524. void LLVOCache::writeToCache(U64 handle, const std::string& region_name,
  1525. const LLUUID& id,
  1526. LLVOCacheEntry::map_t& entry_map,
  1527. bool dirty_cache,
  1528. LLVOCacheEntry::emap_t& extras_map,
  1529. bool removal_enabled)
  1530. {
  1531. LL_TRACY_TIMER(TRC_OBJ_CACHE_WRITE);
  1532. static LLCachedControl<bool> allow_write(gSavedSettings,
  1533. "ObjectDiskCacheWrites");
  1534. if (mReadOnly || !mEnabled || !allow_write)
  1535. {
  1536. return;
  1537. }
  1538. if (!mInitialized)
  1539. {
  1540. llwarns << "Call done while not initialized !" << llendl;
  1541. llassert(false);
  1542. return;
  1543. }
  1544. if (entry_map.empty())
  1545. {
  1546. llinfos << "Empty cache map data for region: " << region_name
  1547. << ". Not writing an object cache file." << llendl;
  1548. return;
  1549. }
  1550. LLTimer write_timer;
  1551. write_timer.reset();
  1552. if (removal_enabled)
  1553. {
  1554. bool has_valid_entry = false;
  1555. for (LLVOCacheEntry::map_t::const_iterator
  1556. iter = entry_map.begin(), end = entry_map.end();
  1557. iter != end; ++iter)
  1558. {
  1559. if (iter->second->isValid())
  1560. {
  1561. has_valid_entry = true;
  1562. break;
  1563. }
  1564. }
  1565. if (!has_valid_entry)
  1566. {
  1567. LL_DEBUGS("ObjectCache") << "Skipping write to cache for region: "
  1568. << region_name
  1569. << ". No valid cache entry." << LL_ENDL;
  1570. return;
  1571. }
  1572. }
  1573. HeaderEntryInfo* entry;
  1574. handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle);
  1575. if (iter == mHandleEntryMap.end()) // New entry
  1576. {
  1577. if (mNumEntries >= mCacheSize - 1)
  1578. {
  1579. purgeEntries(mCacheSize - 1);
  1580. }
  1581. entry = new HeaderEntryInfo();
  1582. entry->mHandle = handle;
  1583. entry->mTime = time(NULL);
  1584. entry->mIndex = mNumEntries++;
  1585. mHeaderEntryQueue.insert(entry);
  1586. mHandleEntryMap[handle] = entry;
  1587. }
  1588. else
  1589. {
  1590. // Update access time.
  1591. entry = iter->second;
  1592. // Resort
  1593. mHeaderEntryQueue.erase(entry);
  1594. entry->mTime = time(NULL);
  1595. mHeaderEntryQueue.insert(entry);
  1596. }
  1597. // Update cache header
  1598. if (!updateEntry(entry))
  1599. {
  1600. llwarns << "Failed to update cache header index " << entry->mIndex
  1601. << " for region: " << region_name << " - handle = " << handle
  1602. << " - Time taken: "
  1603. << write_timer.getElapsedTimeF32() * 1000.f << "ms." << llendl;
  1604. return; // Update failed.
  1605. }
  1606. if (!dirty_cache)
  1607. {
  1608. LL_DEBUGS("ObjectCache") << "Skipping write to cache for region: "
  1609. << region_name << ". Cache not dirty."
  1610. << LL_ENDL;
  1611. return; // Nothing changed, no need to update.
  1612. }
  1613. static LLCachedControl<bool> use_thread_pool(gSavedSettings,
  1614. "ThreadedObjectCacheWrites");
  1615. // Note: cannot queue when shutting down (it would crash). HB
  1616. if (!use_thread_pool || LLApp::isExiting() || !mThreadPoolp)
  1617. {
  1618. WriteWorker worker(handle, id, region_name, entry_map, extras_map,
  1619. removal_enabled);
  1620. worker.writeCacheFile();
  1621. llinfos << "Saved objects for region '" << region_name << "' in "
  1622. << write_timer.getElapsedTimeF32() * 1000.f << "ms." << llendl;
  1623. return;
  1624. }
  1625. // Queue the cache file write
  1626. mThreadPoolp->getQueue().post(
  1627. [worker = WriteWorker(handle, id, region_name, entry_map, extras_map,
  1628. removal_enabled)]() mutable
  1629. {
  1630. LL_TRACY_TIMER(TRC_OBJ_CACHE_THREAD_WRITE);
  1631. // Queued saves are aborted on shutdown to prevent crashes (because
  1632. // LLThreadPool did already shut down on LLApp::isExiting()); this
  1633. // it not a big deal, since it is a *rare* condition (the user must
  1634. // quit or crash just after a LLViewerRegion got deleted and before
  1635. // its queued cache write is performed, meaning within 500ms or so
  1636. // at worst), and it simply means that the corresponding cache file
  1637. // would not be updated. HB
  1638. if (!LLApp::isExiting())
  1639. {
  1640. worker.writeCacheFile();
  1641. }
  1642. });
  1643. llinfos << "Queued cache save operation for region '" << region_name
  1644. << "' in " << write_timer.getElapsedTimeF32() * 1000.f << "ms."
  1645. << llendl;
  1646. }
  1647. ///////////////////////////////////////////////////////////////////////////////
  1648. // LLVOCache::ReadWorker sub-class
  1649. ///////////////////////////////////////////////////////////////////////////////
  1650. LLVOCache::ReadWorker::ReadWorker(U64 handle, const LLUUID& id,
  1651. const std::string& region_name)
  1652. : mId(id),
  1653. mHandle(handle),
  1654. mRegionName(region_name)
  1655. {
  1656. }
  1657. void LLVOCache::ReadWorker::readCacheFile()
  1658. {
  1659. bool success;
  1660. LLVOCacheEntry::map_t* entry_map = NULL;
  1661. // Read from cache file
  1662. std::string filename;
  1663. LLVOCache::getInstance()->getObjectCacheFilename(mHandle, filename);
  1664. bool file_exists = LLFile::exists(filename);
  1665. if (!file_exists)
  1666. {
  1667. success = false;
  1668. llwarns << "Could not find: " << filename << " - Region: "
  1669. << mRegionName << llendl;
  1670. }
  1671. else
  1672. {
  1673. LLFile infile(filename, "rb");
  1674. LLUUID cache_id;
  1675. success = check_read(&infile, cache_id.mData, UUID_BYTES);
  1676. if (success && cache_id != mId)
  1677. {
  1678. success = false;
  1679. llinfos << "Cache Id does not match region: " << mRegionName
  1680. << ". Discarding." << llendl;
  1681. }
  1682. if (success)
  1683. {
  1684. entry_map = new LLVOCacheEntry::map_t();
  1685. S32 num_entries;
  1686. success = check_read(&infile, (U8*)&num_entries, sizeof(S32));
  1687. if (success)
  1688. {
  1689. for (S32 i = 0; i < num_entries && !infile.eof(); ++i)
  1690. {
  1691. LLPointer<LLVOCacheEntry> entry =
  1692. new LLVOCacheEntry(&infile);
  1693. if (!entry->getLocalID())
  1694. {
  1695. success = infile.eof() && !entry_map->empty();
  1696. if (!success)
  1697. {
  1698. llwarns << "Aborting cache file load for "
  1699. << filename
  1700. << ": cache file corruption detected."
  1701. << llendl;
  1702. }
  1703. break;
  1704. }
  1705. entry_map->emplace(entry->getLocalID(), entry);
  1706. }
  1707. }
  1708. }
  1709. }
  1710. if (success)
  1711. {
  1712. llinfos << "Cache hit for region " << mRegionName << " on file: "
  1713. << filename << llendl;
  1714. }
  1715. else
  1716. {
  1717. if (entry_map)
  1718. {
  1719. delete entry_map;
  1720. entry_map = NULL;
  1721. }
  1722. llinfos << "Removing cache entry for region: " << mRegionName
  1723. << llendl;
  1724. LLVOCache::getInstance()->removeEntry(mHandle);
  1725. if (file_exists)
  1726. {
  1727. llinfos << "Removing cache file: " << filename << llendl;
  1728. LLFile::remove(filename);
  1729. }
  1730. }
  1731. // Read extras GLTF materials data, if any and desired.
  1732. LLVOCacheEntry::emap_t* extras_map = NULL;
  1733. while (true)
  1734. {
  1735. LLVOCache::getInstance()->getObjectCacheFilename(mHandle, filename,
  1736. true);
  1737. if (!LLFile::exists(filename))
  1738. {
  1739. // Since not all grids support GLTF, do not spam the log file, unless
  1740. // we do need debugging.
  1741. LL_DEBUGS("ObjectCache") << "No extras cache file: " << filename
  1742. << " - Region: " << mRegionName << llendl;
  1743. break;
  1744. }
  1745. llifstream infile(filename, std::ios::in | std::ios::binary);
  1746. std::string line;
  1747. std::getline(infile, line);
  1748. LLUUID cache_id;
  1749. if (infile.good())
  1750. {
  1751. cache_id.set(line, false);
  1752. }
  1753. bool success = cache_id.notNull();
  1754. if (success && cache_id != mId)
  1755. {
  1756. success = false;
  1757. llwarns << "Extra data cache Id does not match region: "
  1758. << mRegionName << ". Discarding." << llendl;
  1759. }
  1760. while (success)
  1761. {
  1762. S32 num_entries = 0;
  1763. std::getline(infile, line);
  1764. if (infile.good())
  1765. {
  1766. num_entries = atoi(line.c_str());
  1767. }
  1768. if (num_entries <= 0)
  1769. {
  1770. success = false;
  1771. break;
  1772. }
  1773. extras_map = new LLVOCacheEntry::emap_t();
  1774. for (S32 i = 0; i < num_entries && infile.good(); ++i)
  1775. {
  1776. LLSD entry_llsd;
  1777. std::getline(infile, line);
  1778. std::stringstream sstream(line);
  1779. success = LLSDSerialize::fromNotation(entry_llsd, sstream,
  1780. line.size()) > 0;
  1781. if (!success)
  1782. {
  1783. llwarns << "Failure to parse entry " << i
  1784. << " in extras cache for region: " << mRegionName
  1785. << llendl;
  1786. success = false;
  1787. break;
  1788. }
  1789. U32 local_id = entry_llsd["local_id"].asInteger();
  1790. if (!local_id)
  1791. {
  1792. llwarns << "Null local id for entry " << i
  1793. << " in extras cache for region: " << mRegionName
  1794. << llendl;
  1795. continue;
  1796. }
  1797. LLGLTFOverrideCacheEntry entry;
  1798. if (entry.fromLLSD(entry_llsd))
  1799. {
  1800. extras_map->emplace(local_id, entry);
  1801. }
  1802. else
  1803. {
  1804. llwarns << "Failed to read entry for local id " << local_id
  1805. << " in extras cache for region: " << mRegionName
  1806. << ". Data was:\n"
  1807. << ll_pretty_print_sd(entry_llsd) << llendl;
  1808. // Do not keep the corresponding entry in the entry map:
  1809. // it would cause a failure to rez materials since the
  1810. // missing data would not be requested to the server. HB
  1811. if (entry_map)
  1812. {
  1813. entry_map->erase(local_id);
  1814. }
  1815. }
  1816. }
  1817. break;
  1818. }
  1819. infile.close();
  1820. if (success)
  1821. {
  1822. llinfos << "Extra data cache hit for region " << mRegionName
  1823. << " on file: " << filename << llendl;
  1824. break;
  1825. }
  1826. llwarns << "Aborted extra data cache load for region '" << mRegionName
  1827. << ". Removing bad cache file: " << filename << llendl;
  1828. LLFile::remove(filename);
  1829. if (extras_map)
  1830. {
  1831. delete extras_map;
  1832. extras_map = NULL;
  1833. }
  1834. break;
  1835. }
  1836. // Important: the callback shall be called from the main thread. HB
  1837. if (is_main_thread())
  1838. {
  1839. LLViewerRegion::cacheLoadedCallback(mHandle, entry_map, extras_map);
  1840. }
  1841. else if (gMainloopWorkp)
  1842. {
  1843. LL_DEBUGS("ObjectCache") << "Queuing loaded callback for region "
  1844. << mRegionName << " (handle " << mHandle
  1845. << ")" << LL_ENDL;
  1846. // We *MUST* copy the handle on the stack and capture the latter, else
  1847. // we do not capture this->mHandle, but instead get the one of a new
  1848. // worker getting created via LLVOCache::ReadWorker::operator() in the
  1849. // lambda. HB
  1850. U64 handle = mHandle;
  1851. gMainloopWorkp->post([=]()
  1852. {
  1853. LLViewerRegion::cacheLoadedCallback(handle,
  1854. entry_map,
  1855. extras_map);
  1856. });
  1857. }
  1858. }
  1859. ///////////////////////////////////////////////////////////////////////////////
  1860. // LLVOCache::WriteWorker sub-class
  1861. ///////////////////////////////////////////////////////////////////////////////
  1862. LLVOCache::WriteWorker::WriteWorker(U64 handle, const LLUUID& id,
  1863. const std::string& region_name,
  1864. LLVOCacheEntry::map_t& entry_map,
  1865. LLVOCacheEntry::emap_t& extras_map,
  1866. bool removal_enabled)
  1867. : mId(id),
  1868. mHandle(handle),
  1869. mRegionName(region_name),
  1870. mRemovalEnabled(removal_enabled)
  1871. {
  1872. // We swap the maps passed by reference, for speed. It means the referenced
  1873. // maps are emptied, but this is OK; see LLViewerRegion::saveObjectCache()
  1874. // which is currently the only caller for LLVOCache::writeToCache(). HB
  1875. mEntryMap.swap(entry_map);
  1876. mExtraMap.swap(extras_map);
  1877. }
  1878. void LLVOCache::WriteWorker::writeCacheFile()
  1879. {
  1880. // Write to cache file
  1881. std::string filename;
  1882. LLVOCache* cachep = LLVOCache::getInstance();
  1883. cachep->getObjectCacheFilename(mHandle, filename);
  1884. // Write the cache file. Note that we are using "wb" (which overwrites any
  1885. // existing file; this is essential to avoid writing a smaller amount of
  1886. // data in a larger file, which would result in a "corrupted" error on next
  1887. // read to EOF). HB
  1888. LLFile outfile(filename, "wb");
  1889. bool success = check_write(&outfile, (U8*)mId.mData, UUID_BYTES);
  1890. if (success)
  1891. {
  1892. S32 num_entries = mEntryMap.size();
  1893. success = check_write(&outfile, (U8*)&num_entries, sizeof(S32));
  1894. for (LLVOCacheEntry::map_t::const_iterator iter = mEntryMap.begin(),
  1895. end = mEntryMap.end();
  1896. success && iter != end; ++iter)
  1897. {
  1898. if (!mRemovalEnabled || iter->second->isValid())
  1899. {
  1900. success = iter->second->writeToFile(&outfile);
  1901. if (!success)
  1902. {
  1903. break;
  1904. }
  1905. }
  1906. }
  1907. }
  1908. if (!success)
  1909. {
  1910. llwarns << "Aborted cache file write for region " << mRegionName
  1911. << " (failure to write to file: " << filename << ")."
  1912. << llendl;
  1913. cachep->removeEntry(mHandle);
  1914. LLFile::remove(filename);
  1915. }
  1916. // This used to be in a separate LLVOCache::writeExtrasToCache() method.
  1917. // I integrated it here, so to thread this operation as well. HB
  1918. cachep->getObjectCacheFilename(mHandle, filename, true);
  1919. if (mExtraMap.empty())
  1920. {
  1921. if (LLFile::exists(filename))
  1922. {
  1923. llinfos << "Empty extra data for '" << mRegionName
  1924. << ". Removing stale file: " << filename << llendl;
  1925. LLFile::remove(filename);
  1926. }
  1927. return;
  1928. }
  1929. cachep->getObjectCacheFilename(mHandle, filename, true);
  1930. llofstream out_file(filename, std::ios::trunc | std::ios::binary);
  1931. success = out_file.good();
  1932. while (success)
  1933. {
  1934. out_file << mId << '\n' << U32(mExtraMap.size()) << '\n';
  1935. if (!out_file.good())
  1936. {
  1937. success = false;
  1938. break;
  1939. }
  1940. LLSD entry_llsd;
  1941. for (auto const& entry : mExtraMap)
  1942. {
  1943. entry_llsd = entry.second.toLLSD();
  1944. entry_llsd["local_id"] = (LLSD::Integer)entry.first;
  1945. out_file << entry_llsd << '\n';
  1946. if (!out_file.good())
  1947. {
  1948. success = false;
  1949. break;
  1950. }
  1951. }
  1952. break;
  1953. }
  1954. if (success)
  1955. {
  1956. llinfos << "Saved extra data for region '" << mRegionName
  1957. << " to file: " << filename << llendl;
  1958. return;
  1959. }
  1960. llwarns << "Aborted extra cache write for region '" << mRegionName
  1961. << " (failure to write to file: " << filename << ")." << llendl;
  1962. }