MAINT-7119 - [Love Me Render] Issues with RenderAutoMuteByteLimit() versus worn legacy prims, sculpts and non-rigged mesh.

FIXED.
Remark: for Linux platform, for the best times, when we will use gcc > 4.6, otherwise ICE :-(
master
ruslantproductengine 2017-03-03 16:45:46 +02:00
parent 9a525c163e
commit cbffc8194c
6 changed files with 312 additions and 192 deletions

View File

@ -528,6 +528,7 @@ set(viewer_SOURCE_FILES
llscriptfloater.cpp
llscrollingpanelparam.cpp
llscrollingpanelparambase.cpp
llsculptidsize.cpp
llsearchcombobox.cpp
llsearchhistory.cpp
llsecapi.cpp
@ -1140,6 +1141,7 @@ set(viewer_HEADER_FILES
llscriptruntimeperms.h
llscrollingpanelparam.h
llscrollingpanelparambase.h
llsculptidsize.h
llsearchcombobox.h
llsearchhistory.h
llsecapi.h

View File

@ -53,6 +53,7 @@
#include "llviewershadermgr.h"
#include "llviewertexture.h"
#include "llvoavatar.h"
#include "llsculptidsize.h"
#if LL_LINUX
// Work-around spurious used before init warning on Vector4a

View File

@ -0,0 +1,154 @@
/**
* @file llsculptidsize.cpp
* @brief LLSculptIDSize class implementation
*
* $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 "llviewerprecompiledheaders.h"
#include "llsculptidsize.h"
#include "llvovolume.h"
#include "lldrawable.h"
#include "llvoavatar.h"
//boost
#include "boost/make_shared.hpp"
//...........
extern LLControlGroup gSavedSettings;
//...........
typedef std::pair<LLSculptIDSize::container_BY_SCULPT_ID_view::iterator, LLSculptIDSize::container_BY_SCULPT_ID_view::iterator> pair_iter_iter_BY_SCULPT_ID_t;
//...........
void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ }
void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz)
{
llassert(sz >= 0);
if (!pdrawable) return;
LLVOVolume* vvol = pdrawable->getVOVolume();
if (!vvol) return;
if (!vvol->isAttachment()) return;
if (!vvol->getAvatar()) return;
if (vvol->getAvatar()->isSelf()) return;
LLVolume *vol = vvol->getVolume();
if (!vol) return;
const LLUUID &sculptId = vol->getParams().getSculptID();
if (sculptId.isNull()) return;
unsigned int total_size = 0;
pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
if (itLU.first == itLU.second)
{ //register
llassert(mSizeInfo.get<tag_BY_DRAWABLE>().end() == mSizeInfo.get<tag_BY_DRAWABLE>().find(pdrawable));
mSizeInfo.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, boost::make_shared<SizeSum>(sz), sculptId));
total_size = sz;
}
else
{ //update + register
Info &nfo = const_cast<Info &>(*itLU.first);
//calc new size
total_size = nfo.getSizeSum() + sz;
nfo.mSharedSizeSum->mSizeSum = total_size;
nfo.mSize = sz;
//update size for all LLDrwable in range of sculptId
for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it)
{
mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
}
//trying insert the LLDrawable
mSizeInfo.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, nfo.mSharedSizeSum, sculptId));
}
static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit)
{
pair_iter_iter_BY_SCULPT_ID_t it_eqr = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
for (; it_eqr.first != it_eqr.second; ++it_eqr.first)
{
const Info &i = *it_eqr.first;
LLVOVolume *pVVol = i.mDrawable->getVOVolume();
if (pVVol
&& !pVVol->isDead()
&& pVVol->isAttachment()
&& !pVVol->getAvatar()->isSelf()
&& LLVOVolume::NO_LOD != pVVol->getLOD()
)
{
addToUnloaded(sculptId);
//immediately
const_cast<LLDrawable*>(i.mDrawable)->unload();
}
}
}
}
void LLSculptIDSize::dec(const LLDrawable *pdrawable)
{
container_BY_DRAWABLE_view::iterator it = mSizeInfo.get<tag_BY_DRAWABLE>().find(pdrawable);
if (mSizeInfo.get<tag_BY_DRAWABLE>().end() == it) return;
unsigned int size = it->getSizeSum() - it->getSize();
if (0 == size)
{
mSizeInfo.get<tag_BY_SCULPT_ID>().erase(it->getSculptId());
}
else
{
Info &nfo = const_cast<Info &>(*it);
nfo.mSize = 0;
pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(it->getSculptId());
it->mSharedSizeSum->mSizeSum = size;
for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it)
{
mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
}
}
}
void LLSculptIDSize::rem(const LLUUID &sculptId)
{
mSizeInfo.get<tag_BY_SCULPT_ID>().erase(sculptId);
}
void LLSculptIDSize::resetSizeSum(const LLUUID &sculptId)
{
const pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
if (itLU.first != itLU.second) {
itLU.first->mSharedSizeSum->mSizeSum = 0;
}
for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first, itE = itLU.second; it != itE; ++it)
{
mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
}
}

View File

@ -0,0 +1,134 @@
/**
* @file llsculptidsize.h
* @brief LLSculptIDSize class definition
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLSCULPTIDSIZE_H
#define LL_LLSCULPTIDSIZE_H
#include "lluuid.h"
//std
#include <set>
//boost
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/ordered_index.hpp"
#include "boost/multi_index/mem_fun.hpp"
class LLDrawable;
class LLSculptIDSize
{
public:
struct SizeSum
{
SizeSum(int size)
: mSizeSum(size)
{}
unsigned int mSizeSum;
};
struct Info
{
typedef boost::shared_ptr<SizeSum> PtrSizeSum;
Info(const LLDrawable *drawable, int size, PtrSizeSum sizeInfo, LLUUID sculptId)
: mDrawable(drawable)
, mSize(size)
, mSharedSizeSum(sizeInfo)
, mSculptId(sculptId)
{}
const LLDrawable *mDrawable;
unsigned int mSize;
PtrSizeSum mSharedSizeSum;
LLUUID mSculptId;
inline const LLDrawable* getPtrLLDrawable() const { return mDrawable; }
inline unsigned int getSize() const { return mSize; }
inline unsigned int getSizeSum() const { return mSharedSizeSum->mSizeSum; }
inline LLUUID getSculptId() const { return mSculptId; }
PtrSizeSum getSizeInfo() { return mSharedSizeSum; }
};
public:
//tags
struct tag_BY_DRAWABLE {};
struct tag_BY_SCULPT_ID {};
struct tag_BY_SIZE {};
//container
typedef boost::multi_index_container <
Info,
boost::multi_index::indexed_by <
boost::multi_index::ordered_unique< boost::multi_index::tag<tag_BY_DRAWABLE>
, boost::multi_index::const_mem_fun<Info, const LLDrawable*, &Info::getPtrLLDrawable>
>
, boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SCULPT_ID>
, boost::multi_index::const_mem_fun<Info, LLUUID, &Info::getSculptId>
>
, boost::multi_index::ordered_non_unique < boost::multi_index::tag<tag_BY_SIZE>
, boost::multi_index::const_mem_fun < Info, unsigned int, &Info::getSizeSum >
>
>
> container;
//views
typedef container::index<tag_BY_DRAWABLE>::type container_BY_DRAWABLE_view;
typedef container::index<tag_BY_SCULPT_ID>::type container_BY_SCULPT_ID_view;
typedef container::index<tag_BY_SIZE>::type container_BY_SIZE_view;
private:
LLSculptIDSize()
{}
public:
static LLSculptIDSize & instance()
{
static LLSculptIDSize inst;
return inst;
}
public:
void inc(const LLDrawable *pdrawable, int sz);
void dec(const LLDrawable *pdrawable);
void rem(const LLUUID &sculptId);
inline void addToUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.insert(sculptId); }
inline void remFromUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.erase(sculptId); }
inline bool isUnloaded(const LLUUID &sculptId) const { return mMarkAsUnloaded.end() != mMarkAsUnloaded.find(sculptId); }
inline void clearUnloaded() { mMarkAsUnloaded.clear(); }
void resetSizeSum(const LLUUID &sculptId);
inline const container & getSizeInfo() const { return mSizeInfo; }
private:
container mSizeInfo;
typedef std::set<LLUUID> std_LLUUID;
std_LLUUID mMarkAsUnloaded;
};
#endif

View File

@ -78,6 +78,7 @@
#include "llvoavatar.h"
#include "llvocache.h"
#include "llmaterialmgr.h"
#include "llsculptidsize.h"
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
@ -1057,12 +1058,13 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
LLFace::cacheFaceInVRAM(face);
}
}
return TRUE;
}
else if (NO_LOD == lod)
{
LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID());
}
return FALSE;
}
@ -1304,7 +1306,8 @@ BOOL LLVOVolume::calcLOD()
if (cur_detail != mLOD)
{
mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
mLOD = cur_detail;
mLOD = cur_detail;
return TRUE;
}
@ -1318,7 +1321,16 @@ BOOL LLVOVolume::updateLOD()
return FALSE;
}
BOOL lod_changed = calcLOD();
BOOL lod_changed = FALSE;
if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID()))
{
lod_changed = calcLOD();
}
else
{
return FALSE;
}
if (lod_changed)
{
@ -4679,6 +4691,7 @@ void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
{
//postponed
pVVol->markForUnload();
LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId());
}
}
@ -4697,6 +4710,7 @@ void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
&& LLVOVolume::NO_LOD == pVVol->getLOD()
)
{
LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId());
pVVol->updateLOD();
pVVol->markForUpdate(TRUE);
}
@ -4704,6 +4718,8 @@ void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
}
else
{
LLSculptIDSize::instance().clearUnloaded();
LLSculptIDSize::container_BY_SIZE_view::iterator
itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(),
itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end();
@ -6168,104 +6184,3 @@ void LLHUDPartition::shift(const LLVector4a &offset)
{
//HUD objects don't shift with region crossing. That would be silly.
}
//...........
void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ }
void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz)
{
llassert(sz >= 0);
if (!pdrawable) return;
LLVOVolume* vvol = pdrawable->getVOVolume();
if (!vvol) return;
if (!vvol->isAttachment()) return;
if (!vvol->getAvatar()) return;
if (vvol->getAvatar()->isSelf()) return;
LLVolume *vol = vvol->getVolume();
if (!vol) return;
const LLUUID &sculptId = vol->getParams().getSculptID();
unsigned int total_size = 0;
typedef std::pair<container_BY_SCULPT_ID_view::iterator, container_BY_SCULPT_ID_view::iterator> pair_iter_iter_t;
pair_iter_iter_t itLU = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
if (itLU.first == itLU.second)
{ //register
llassert(m_size_info.get<tag_BY_DRAWABLE>().end() == m_size_info.get<tag_BY_DRAWABLE>().find(pdrawable));
m_size_info.get<tag_BY_DRAWABLE>().insert(Info( pdrawable, sz, boost::make_shared<SizeInfo>(sz), sculptId ));
total_size = sz;
}
else
{ //update + register
Info &nfo = const_cast<Info &>(*itLU.first);
//calc new size
total_size = nfo.getTotalSize() + sz;
nfo.m_p_size_info->m_size = total_size;
nfo.m_size = sz;
//update size for all LLDrwable in range of sculptId
for (pair_iter_iter_t::first_type it = itLU.first; it != itLU.second; ++it)
{
m_size_info.get<tag_BY_SIZE>().modify_key(m_size_info.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
}
//trying insert the LLDrawable
m_size_info.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, nfo.m_p_size_info, sculptId));
}
static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit)
{
pair_iter_iter_t it_eqr = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(sculptId);
for (; it_eqr.first != it_eqr.second; ++it_eqr.first)
{
const Info &i = *it_eqr.first;
LLVOVolume *pVVol = i.m_p_drawable->getVOVolume();
if (pVVol
&& !pVVol->isDead()
&& pVVol->isAttachment()
&& !pVVol->getAvatar()->isSelf()
&& LLVOVolume::NO_LOD != pVVol->getLOD()
)
{
//immediately
const_cast<LLDrawable*>(i.m_p_drawable)->unload();
}
}
}
}
void LLSculptIDSize::dec(const LLDrawable *pdrawable)
{
container_BY_DRAWABLE_view::iterator it = m_size_info.get<tag_BY_DRAWABLE>().find(pdrawable);
if (m_size_info.get<tag_BY_DRAWABLE>().end() == it) return;
unsigned int size = it->getTotalSize() - it->getSize();
if (0 == size)
{
m_size_info.get<tag_BY_SCULPT_ID>().erase(it->getSculptId());
}
else
{
Info &nfo = const_cast<Info &>(*it);
nfo.m_size = 0;
typedef std::pair<container_BY_SCULPT_ID_view::iterator, container_BY_SCULPT_ID_view::iterator> pair_iter_iter_t;
pair_iter_iter_t itLU = m_size_info.get<tag_BY_SCULPT_ID>().equal_range(it->getSculptId());
it->m_p_size_info->m_size = size;
for (pair_iter_iter_t::first_type it = itLU.first; it != itLU.second; ++it)
{
m_size_info.get<tag_BY_SIZE>().modify_key(m_size_info.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1));
}
}
}
void LLSculptIDSize::rem(LLUUID sculptId)
{
m_size_info.get<tag_BY_SCULPT_ID>().erase(sculptId);
}

View File

@ -36,10 +36,6 @@
#include "m4math.h" // LLMatrix4
#include <map>
#include <set>
//boost
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/ordered_index.hpp"
#include "boost/multi_index/mem_fun.hpp"
class LLViewerTextureAnim;
@ -418,87 +414,5 @@ private:
};
//...........
class LLSculptIDSize
{
public:
struct SizeInfo
{
SizeInfo(int size) : m_size(size) {}
unsigned int m_size;
};
struct Info
{
typedef boost::shared_ptr<SizeInfo> PtrSizeInfo;
Info(const LLDrawable *pdrawable, int size, PtrSizeInfo psize_info, LLUUID sculpt_id)
: m_p_drawable(pdrawable)
, m_size(size)
, m_p_size_info(psize_info)
, m_sculpt_id(sculpt_id)
{}
const LLDrawable *m_p_drawable;
unsigned int m_size;
PtrSizeInfo m_p_size_info;
LLUUID m_sculpt_id;
inline const LLDrawable* getPtrLLDrawable() const { return m_p_drawable; }
inline unsigned int getSize() const { return m_size; }
inline unsigned int getTotalSize() const { return m_p_size_info->m_size; }
inline LLUUID getSculptId() const { return m_sculpt_id; }
PtrSizeInfo getSizeInfo() { return m_p_size_info; }
};
public:
//tags
struct tag_BY_DRAWABLE {};
struct tag_BY_SCULPT_ID {};
struct tag_BY_SIZE {};
//container
typedef boost::multi_index_container <
Info,
boost::multi_index::indexed_by <
boost::multi_index::ordered_unique< boost::multi_index::tag<tag_BY_DRAWABLE>
, boost::multi_index::const_mem_fun<Info, const LLDrawable*, &Info::getPtrLLDrawable>
>
, boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SCULPT_ID>
, boost::multi_index::const_mem_fun<Info, LLUUID, &Info::getSculptId>
>
, boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SIZE>
, boost::multi_index::const_mem_fun<Info, unsigned int, &Info::getTotalSize>
>
>
> container;
//views
typedef container::index<tag_BY_DRAWABLE>::type container_BY_DRAWABLE_view;
typedef container::index<tag_BY_SCULPT_ID>::type container_BY_SCULPT_ID_view;
typedef container::index<tag_BY_SIZE>::type container_BY_SIZE_view;
private:
LLSculptIDSize()
{}
public:
static LLSculptIDSize & instance() {
static LLSculptIDSize inst;
return inst;
}
public:
void inc(const LLDrawable *pdrawable, int sz);
void dec(const LLDrawable *pdrawable);
void rem(LLUUID sculptId);
const container & getSizeInfo() const { return m_size_info; }
private:
container m_size_info;
};
#endif // LL_LLVOVOLUME_H