summaryrefslogtreecommitdiff
path: root/indra/llmath/llvolumemgr.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 21:25:21 +0200
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-22 22:40:26 +0300
commite2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch)
tree1bb897489ce524986f6196201c10ac0d8861aa5f /indra/llmath/llvolumemgr.cpp
parent069ea06848f766466f1a281144c82a0f2bd79f3a (diff)
Fix line endlings
Diffstat (limited to 'indra/llmath/llvolumemgr.cpp')
-rw-r--r--indra/llmath/llvolumemgr.cpp816
1 files changed, 408 insertions, 408 deletions
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp
index f796fbf551..bb0c94d513 100644
--- a/indra/llmath/llvolumemgr.cpp
+++ b/indra/llmath/llvolumemgr.cpp
@@ -1,408 +1,408 @@
-/**
- * @file llvolumemgr.cpp
- *
- * $LicenseInfo:firstyear=2002&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$
- */
-
-#include "linden_common.h"
-
-#include "llvolumemgr.h"
-#include "llvolume.h"
-
-
-const F32 BASE_THRESHOLD = 0.03f;
-
-//static
-F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
- 2*BASE_THRESHOLD,
- 8*BASE_THRESHOLD,
- 100*BASE_THRESHOLD};
-
-//static
-F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
-
-
-//============================================================================
-
-LLVolumeMgr::LLVolumeMgr()
-: mDataMutex(NULL)
-{
- // the LLMutex magic interferes with easy unit testing,
- // so you now must manually call useMutex() to use it
- //mDataMutex = new LLMutex();
-}
-
-LLVolumeMgr::~LLVolumeMgr()
-{
- cleanup();
-
- delete mDataMutex;
- mDataMutex = NULL;
-}
-
-bool LLVolumeMgr::cleanup()
-{
- bool no_refs = true;
- if (mDataMutex)
- {
- mDataMutex->lock();
- }
- for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
- end = mVolumeLODGroups.end();
- iter != end; iter++)
- {
- LLVolumeLODGroup *volgroupp = iter->second;
- if (!volgroupp->cleanupRefs())
- {
- no_refs = false;
- }
- delete volgroupp;
- }
- mVolumeLODGroups.clear();
- if (mDataMutex)
- {
- mDataMutex->unlock();
- }
- return no_refs;
-}
-
-// Always only ever store the results of refVolume in a LLPointer
-// Note however that LLVolumeLODGroup that contains the volume
-// also holds a LLPointer so the volume will only go away after
-// anything holding the volume and the LODGroup are destroyed
-LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 lod)
-{
- LLVolumeLODGroup* volgroupp;
- if (mDataMutex)
- {
- mDataMutex->lock();
- }
- volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
- if( iter == mVolumeLODGroups.end() )
- {
- volgroupp = createNewGroup(volume_params);
- }
- else
- {
- volgroupp = iter->second;
- }
- if (mDataMutex)
- {
- mDataMutex->unlock();
- }
- return volgroupp->refLOD(lod);
-}
-
-// virtual
-LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const
-{
- LLVolumeLODGroup* volgroupp = NULL;
- if (mDataMutex)
- {
- mDataMutex->lock();
- }
- volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params);
- if( iter != mVolumeLODGroups.end() )
- {
- volgroupp = iter->second;
- }
- if (mDataMutex)
- {
- mDataMutex->unlock();
- }
- return volgroupp;
-}
-
-void LLVolumeMgr::unrefVolume(LLVolume *volumep)
-{
- if (volumep->isUnique())
- {
- // TomY: Don't need to manage this volume. It is a unique instance.
- return;
- }
- const LLVolumeParams* params = &(volumep->getParams());
- if (mDataMutex)
- {
- mDataMutex->lock();
- }
- volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
- if( iter == mVolumeLODGroups.end() )
- {
- LL_ERRS() << "Warning! Tried to cleanup unknown volume type! " << *params << LL_ENDL;
- if (mDataMutex)
- {
- mDataMutex->unlock();
- }
- return;
- }
- else
- {
- LLVolumeLODGroup* volgroupp = iter->second;
-
- volgroupp->derefLOD(volumep);
- if (volgroupp->getNumRefs() == 0)
- {
- mVolumeLODGroups.erase(params);
- delete volgroupp;
- }
- }
- if (mDataMutex)
- {
- mDataMutex->unlock();
- }
-
-}
-
-// protected
-void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup)
-{
- mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup;
-}
-
-// protected
-LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params)
-{
- LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params);
- insertGroup(volgroup);
- return volgroup;
-}
-
-// virtual
-void LLVolumeMgr::dump()
-{
- F32 avg = 0.f;
- if (mDataMutex)
- {
- mDataMutex->lock();
- }
- for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
- end = mVolumeLODGroups.end();
- iter != end; iter++)
- {
- LLVolumeLODGroup *volgroupp = iter->second;
- avg += volgroupp->dump();
- }
- int count = (int)mVolumeLODGroups.size();
- avg = count ? avg / (F32)count : 0.0f;
- if (mDataMutex)
- {
- mDataMutex->unlock();
- }
- LL_INFOS() << "Average usage of LODs " << avg << LL_ENDL;
-}
-
-void LLVolumeMgr::useMutex()
-{
- if (!mDataMutex)
- {
- mDataMutex = new LLMutex();
- }
-}
-
-std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
-{
- s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
-
- S32 total_refs = 0;
- if (volume_mgr.mDataMutex)
- {
- volume_mgr.mDataMutex->lock();
- }
-
- for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin();
- iter != volume_mgr.mVolumeLODGroups.end(); ++iter)
- {
- LLVolumeLODGroup *volgroupp = iter->second;
- total_refs += volgroupp->getNumRefs();
- s << ", " << (*volgroupp);
- }
-
- if (volume_mgr.mDataMutex)
- {
- volume_mgr.mDataMutex->unlock();
- }
-
- s << ", total_refs=" << total_refs << " }";
- return s;
-}
-
-LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
- : mVolumeParams(params),
- mRefs(0)
-{
- for (S32 i = 0; i < NUM_LODS; i++)
- {
- mLODRefs[i] = 0;
- mAccessCount[i] = 0;
- }
-}
-
-LLVolumeLODGroup::~LLVolumeLODGroup()
-{
- for (S32 i = 0; i < NUM_LODS; i++)
- {
- llassert_always(mLODRefs[i] == 0);
- }
-}
-
-// Called from LLVolumeMgr::cleanup
-bool LLVolumeLODGroup::cleanupRefs()
-{
- bool res = true;
- if (mRefs != 0)
- {
- LL_WARNS() << "Volume group has remaining refs:" << getNumRefs() << LL_ENDL;
- mRefs = 0;
- for (S32 i = 0; i < NUM_LODS; i++)
- {
- if (mLODRefs[i] > 0)
- {
- LL_WARNS() << " LOD " << i << " refs = " << mLODRefs[i] << LL_ENDL;
- mLODRefs[i] = 0;
- mVolumeLODs[i] = NULL;
- }
- }
- LL_WARNS() << *getVolumeParams() << LL_ENDL;
- res = false;
- }
- return res;
-}
-
-LLVolume* LLVolumeLODGroup::refLOD(const S32 lod)
-{
- llassert(lod >=0 && lod < NUM_LODS);
- mAccessCount[lod]++;
-
- mRefs++;
- if (mVolumeLODs[lod].isNull())
- {
- mVolumeLODs[lod] = new LLVolume(mVolumeParams, mDetailScales[lod]);
- }
- mLODRefs[lod]++;
- return mVolumeLODs[lod];
-}
-
-bool LLVolumeLODGroup::derefLOD(LLVolume *volumep)
-{
- llassert_always(mRefs > 0);
- mRefs--;
- for (S32 i = 0; i < NUM_LODS; i++)
- {
- if (mVolumeLODs[i] == volumep)
- {
- llassert_always(mLODRefs[i] > 0);
- mLODRefs[i]--;
-#if 0 // SJB: Possible opt: keep other lods around
- if (!mLODRefs[i])
- {
- mVolumeLODs[i] = NULL;
- }
-#endif
- return true;
- }
- }
- LL_ERRS() << "Deref of non-matching LOD in volume LOD group" << LL_ENDL;
- return false;
-}
-
-S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
-{
- S32 i = 0;
- while (i < (NUM_LODS - 1))
- {
- if (tan_angle <= mDetailThresholds[i])
- {
- return i;
- }
- i++;
- }
- return NUM_LODS - 1;
-}
-
-void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher)
-{
- S32 detail = getDetailFromTan(tan_angle);
-
- if (detail > 0)
- {
- to_lower = tan_angle - mDetailThresholds[detail];
- }
- else
- {
- to_lower = 1024.f*1024.f;
- }
-
- if (detail < NUM_LODS-1)
- {
- to_higher = mDetailThresholds[detail+1] - tan_angle;
- }
- else
- {
- to_higher = 1024.f*1024.f;
- }
-}
-
-F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
-{
- return mDetailScales[detail];
-}
-
-S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail)
-{
- for (S32 i = 1; i < 4; i++)
- {
- if (mDetailScales[i] > detail)
- {
- return i-1;
- }
- }
-
- return 3;
-}
-
-F32 LLVolumeLODGroup::dump()
-{
- F32 usage = 0.f;
- for (S32 i = 0; i < NUM_LODS; i++)
- {
- if (mAccessCount[i] > 0)
- {
- usage += 1.f;
- }
- }
- usage = usage / (F32)NUM_LODS;
-
- std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
-
- LL_INFOS() << dump_str << LL_ENDL;
- return usage;
-}
-
-std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
-{
- s << "{ numRefs=" << volgroup.getNumRefs();
- s << ", mParams=" << volgroup.getVolumeParams();
- s << " }";
-
- return s;
-}
-
+/**
+ * @file llvolumemgr.cpp
+ *
+ * $LicenseInfo:firstyear=2002&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$
+ */
+
+#include "linden_common.h"
+
+#include "llvolumemgr.h"
+#include "llvolume.h"
+
+
+const F32 BASE_THRESHOLD = 0.03f;
+
+//static
+F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
+ 2*BASE_THRESHOLD,
+ 8*BASE_THRESHOLD,
+ 100*BASE_THRESHOLD};
+
+//static
+F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
+
+
+//============================================================================
+
+LLVolumeMgr::LLVolumeMgr()
+: mDataMutex(NULL)
+{
+ // the LLMutex magic interferes with easy unit testing,
+ // so you now must manually call useMutex() to use it
+ //mDataMutex = new LLMutex();
+}
+
+LLVolumeMgr::~LLVolumeMgr()
+{
+ cleanup();
+
+ delete mDataMutex;
+ mDataMutex = NULL;
+}
+
+bool LLVolumeMgr::cleanup()
+{
+ bool no_refs = true;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
+ end = mVolumeLODGroups.end();
+ iter != end; iter++)
+ {
+ LLVolumeLODGroup *volgroupp = iter->second;
+ if (!volgroupp->cleanupRefs())
+ {
+ no_refs = false;
+ }
+ delete volgroupp;
+ }
+ mVolumeLODGroups.clear();
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return no_refs;
+}
+
+// Always only ever store the results of refVolume in a LLPointer
+// Note however that LLVolumeLODGroup that contains the volume
+// also holds a LLPointer so the volume will only go away after
+// anything holding the volume and the LODGroup are destroyed
+LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32 lod)
+{
+ LLVolumeLODGroup* volgroupp;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params);
+ if( iter == mVolumeLODGroups.end() )
+ {
+ volgroupp = createNewGroup(volume_params);
+ }
+ else
+ {
+ volgroupp = iter->second;
+ }
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return volgroupp->refLOD(lod);
+}
+
+// virtual
+LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const
+{
+ LLVolumeLODGroup* volgroupp = NULL;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params);
+ if( iter != mVolumeLODGroups.end() )
+ {
+ volgroupp = iter->second;
+ }
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return volgroupp;
+}
+
+void LLVolumeMgr::unrefVolume(LLVolume *volumep)
+{
+ if (volumep->isUnique())
+ {
+ // TomY: Don't need to manage this volume. It is a unique instance.
+ return;
+ }
+ const LLVolumeParams* params = &(volumep->getParams());
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
+ if( iter == mVolumeLODGroups.end() )
+ {
+ LL_ERRS() << "Warning! Tried to cleanup unknown volume type! " << *params << LL_ENDL;
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ return;
+ }
+ else
+ {
+ LLVolumeLODGroup* volgroupp = iter->second;
+
+ volgroupp->derefLOD(volumep);
+ if (volgroupp->getNumRefs() == 0)
+ {
+ mVolumeLODGroups.erase(params);
+ delete volgroupp;
+ }
+ }
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+
+}
+
+// protected
+void LLVolumeMgr::insertGroup(LLVolumeLODGroup* volgroup)
+{
+ mVolumeLODGroups[volgroup->getVolumeParams()] = volgroup;
+}
+
+// protected
+LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params)
+{
+ LLVolumeLODGroup* volgroup = new LLVolumeLODGroup(volume_params);
+ insertGroup(volgroup);
+ return volgroup;
+}
+
+// virtual
+void LLVolumeMgr::dump()
+{
+ F32 avg = 0.f;
+ if (mDataMutex)
+ {
+ mDataMutex->lock();
+ }
+ for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(),
+ end = mVolumeLODGroups.end();
+ iter != end; iter++)
+ {
+ LLVolumeLODGroup *volgroupp = iter->second;
+ avg += volgroupp->dump();
+ }
+ int count = (int)mVolumeLODGroups.size();
+ avg = count ? avg / (F32)count : 0.0f;
+ if (mDataMutex)
+ {
+ mDataMutex->unlock();
+ }
+ LL_INFOS() << "Average usage of LODs " << avg << LL_ENDL;
+}
+
+void LLVolumeMgr::useMutex()
+{
+ if (!mDataMutex)
+ {
+ mDataMutex = new LLMutex();
+ }
+}
+
+std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr)
+{
+ s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", ";
+
+ S32 total_refs = 0;
+ if (volume_mgr.mDataMutex)
+ {
+ volume_mgr.mDataMutex->lock();
+ }
+
+ for (LLVolumeMgr::volume_lod_group_map_t::const_iterator iter = volume_mgr.mVolumeLODGroups.begin();
+ iter != volume_mgr.mVolumeLODGroups.end(); ++iter)
+ {
+ LLVolumeLODGroup *volgroupp = iter->second;
+ total_refs += volgroupp->getNumRefs();
+ s << ", " << (*volgroupp);
+ }
+
+ if (volume_mgr.mDataMutex)
+ {
+ volume_mgr.mDataMutex->unlock();
+ }
+
+ s << ", total_refs=" << total_refs << " }";
+ return s;
+}
+
+LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams &params)
+ : mVolumeParams(params),
+ mRefs(0)
+{
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ mLODRefs[i] = 0;
+ mAccessCount[i] = 0;
+ }
+}
+
+LLVolumeLODGroup::~LLVolumeLODGroup()
+{
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ llassert_always(mLODRefs[i] == 0);
+ }
+}
+
+// Called from LLVolumeMgr::cleanup
+bool LLVolumeLODGroup::cleanupRefs()
+{
+ bool res = true;
+ if (mRefs != 0)
+ {
+ LL_WARNS() << "Volume group has remaining refs:" << getNumRefs() << LL_ENDL;
+ mRefs = 0;
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ if (mLODRefs[i] > 0)
+ {
+ LL_WARNS() << " LOD " << i << " refs = " << mLODRefs[i] << LL_ENDL;
+ mLODRefs[i] = 0;
+ mVolumeLODs[i] = NULL;
+ }
+ }
+ LL_WARNS() << *getVolumeParams() << LL_ENDL;
+ res = false;
+ }
+ return res;
+}
+
+LLVolume* LLVolumeLODGroup::refLOD(const S32 lod)
+{
+ llassert(lod >=0 && lod < NUM_LODS);
+ mAccessCount[lod]++;
+
+ mRefs++;
+ if (mVolumeLODs[lod].isNull())
+ {
+ mVolumeLODs[lod] = new LLVolume(mVolumeParams, mDetailScales[lod]);
+ }
+ mLODRefs[lod]++;
+ return mVolumeLODs[lod];
+}
+
+bool LLVolumeLODGroup::derefLOD(LLVolume *volumep)
+{
+ llassert_always(mRefs > 0);
+ mRefs--;
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ if (mVolumeLODs[i] == volumep)
+ {
+ llassert_always(mLODRefs[i] > 0);
+ mLODRefs[i]--;
+#if 0 // SJB: Possible opt: keep other lods around
+ if (!mLODRefs[i])
+ {
+ mVolumeLODs[i] = NULL;
+ }
+#endif
+ return true;
+ }
+ }
+ LL_ERRS() << "Deref of non-matching LOD in volume LOD group" << LL_ENDL;
+ return false;
+}
+
+S32 LLVolumeLODGroup::getDetailFromTan(const F32 tan_angle)
+{
+ S32 i = 0;
+ while (i < (NUM_LODS - 1))
+ {
+ if (tan_angle <= mDetailThresholds[i])
+ {
+ return i;
+ }
+ i++;
+ }
+ return NUM_LODS - 1;
+}
+
+void LLVolumeLODGroup::getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher)
+{
+ S32 detail = getDetailFromTan(tan_angle);
+
+ if (detail > 0)
+ {
+ to_lower = tan_angle - mDetailThresholds[detail];
+ }
+ else
+ {
+ to_lower = 1024.f*1024.f;
+ }
+
+ if (detail < NUM_LODS-1)
+ {
+ to_higher = mDetailThresholds[detail+1] - tan_angle;
+ }
+ else
+ {
+ to_higher = 1024.f*1024.f;
+ }
+}
+
+F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
+{
+ return mDetailScales[detail];
+}
+
+S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail)
+{
+ for (S32 i = 1; i < 4; i++)
+ {
+ if (mDetailScales[i] > detail)
+ {
+ return i-1;
+ }
+ }
+
+ return 3;
+}
+
+F32 LLVolumeLODGroup::dump()
+{
+ F32 usage = 0.f;
+ for (S32 i = 0; i < NUM_LODS; i++)
+ {
+ if (mAccessCount[i] > 0)
+ {
+ usage += 1.f;
+ }
+ }
+ usage = usage / (F32)NUM_LODS;
+
+ std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
+
+ LL_INFOS() << dump_str << LL_ENDL;
+ return usage;
+}
+
+std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup)
+{
+ s << "{ numRefs=" << volgroup.getNumRefs();
+ s << ", mParams=" << volgroup.getVolumeParams();
+ s << " }";
+
+ return s;
+}
+