Add debug floater to show how much texture memory objects in view use (per object).
parent
82d306084b
commit
bb0329d012
|
|
@ -192,7 +192,10 @@ protected:
|
|||
protected:
|
||||
LLGLTextureState mTextureState ;
|
||||
|
||||
|
||||
// <FS>ND> Expose mipmap generation so we can check it for texture memory tax
|
||||
public:
|
||||
bool getUseMipMaps() const { return mUseMipMaps; }
|
||||
// </FS:ND>
|
||||
};
|
||||
|
||||
#endif // LL_GL_TEXTURE_H
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ set(viewer_SOURCE_FILES
|
|||
lggcontactsets.cpp
|
||||
lfsimfeaturehandler.cpp
|
||||
llpanelopenregionsettings.cpp
|
||||
fsfloatervramusage.cpp
|
||||
|
||||
llaccountingcostmanager.cpp
|
||||
llagent.cpp
|
||||
|
|
@ -926,6 +927,7 @@ set(viewer_HEADER_FILES
|
|||
lggbeamscolors.h
|
||||
lggcontactsets.h
|
||||
lfsimfeaturehandler.h
|
||||
fsfloatervramusage.h
|
||||
|
||||
llaccountingcostmanager.h
|
||||
llagent.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,343 @@
|
|||
/**
|
||||
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (c) 2015 Nicky Dasmijn
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "fsfloatervramusage.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "lldrawable.h"
|
||||
#include "llviewertexture.h"
|
||||
#include "lltoolpie.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llface.h"
|
||||
#include "llvertexbuffer.h"
|
||||
#include "llcallbacklist.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llagentcamera.h"
|
||||
|
||||
const F32 PROPERTIES_REQUEST_TIMEOUT = 10.0f;
|
||||
const F32 PROPERY_REQUEST_INTERVAL = 2.0f;
|
||||
const U32 PROPERTIES_MAX_REQUEST_COUNT = 250;
|
||||
|
||||
static void onIdle( void *aData )
|
||||
{
|
||||
FSFloaterVRAMUsage *pFloater = reinterpret_cast<FSFloaterVRAMUsage*>(aData);
|
||||
pFloater->onIdle();
|
||||
}
|
||||
|
||||
struct ObjectStat
|
||||
{
|
||||
LLUUID mId;
|
||||
U32 mTextureSize;
|
||||
};
|
||||
|
||||
struct FSFloaterVRAMUsage::ImplData
|
||||
{
|
||||
LLScrollListCtrl *mList;
|
||||
LLObjectSelectionHandle mSelection;
|
||||
U32 mPending;
|
||||
LLFrameTimer mPropTimer;
|
||||
|
||||
std::deque< ObjectStat > mObjects;
|
||||
};
|
||||
|
||||
bool sortByTexture( ObjectStat const &lhs, ObjectStat const &rhs )
|
||||
{
|
||||
return lhs.mTextureSize > rhs.mTextureSize;
|
||||
}
|
||||
|
||||
FSFloaterVRAMUsage::FSFloaterVRAMUsage(const LLSD& seed)
|
||||
: LLFloater( seed )
|
||||
{
|
||||
mData = new ImplData();
|
||||
mData->mList = 0;
|
||||
mData->mPending = 0;
|
||||
|
||||
gIdleCallbacks.addFunction( &::onIdle, this) ;
|
||||
}
|
||||
|
||||
FSFloaterVRAMUsage::~FSFloaterVRAMUsage()
|
||||
{
|
||||
gIdleCallbacks.deleteFunction( &::onIdle, this );
|
||||
delete mData;
|
||||
LLSelectMgr::instance().removePropertyListener( this );
|
||||
LLSelectMgr::instance().enableSilhouette( TRUE );
|
||||
}
|
||||
|
||||
void FSFloaterVRAMUsage::onOpen(const LLSD& key)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL FSFloaterVRAMUsage::postBuild()
|
||||
{
|
||||
LLButton *pRefresh = getChild< LLButton >( "refresh_button" );
|
||||
pRefresh->setClickedCallback( boost::bind( &FSFloaterVRAMUsage::doRefresh, this ) );
|
||||
|
||||
mData->mList = getChild< LLScrollListCtrl >( "result_list" );
|
||||
|
||||
LLSelectMgr::instance().registerPropertyListener( this );
|
||||
LLSelectMgr::instance().enableSilhouette( FALSE );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void FSFloaterVRAMUsage::onIdle()
|
||||
{
|
||||
if( !mData->mPending && mData->mObjects.empty() )
|
||||
{
|
||||
LLSelectMgr::instance().deselectAll();
|
||||
return;
|
||||
}
|
||||
|
||||
if( mData->mPending && mData->mPropTimer.getElapsedTimeF32() < PROPERTIES_REQUEST_TIMEOUT )
|
||||
return;
|
||||
|
||||
if( !mData->mPending && mData->mPropTimer.getStarted() && mData->mPropTimer.getElapsedTimeF32() < PROPERY_REQUEST_INTERVAL )
|
||||
return;
|
||||
|
||||
LLSelectMgr::instance().deselectAll();
|
||||
mData->mPending = 0;
|
||||
|
||||
std::vector< LLViewerObject* > vctSelection;
|
||||
std::deque< ObjectStat > withoutRegion;
|
||||
|
||||
while( mData->mPending < PROPERTIES_MAX_REQUEST_COUNT && !mData->mObjects.empty() )
|
||||
{
|
||||
LLViewerObject *pObj = gObjectList.findObject( mData->mObjects[ 0 ].mId );
|
||||
if( pObj && pObj->getRegion() )
|
||||
{
|
||||
++mData->mPending;
|
||||
vctSelection.push_back( pObj );
|
||||
}
|
||||
else if( pObj )
|
||||
withoutRegion.push_back( mData->mObjects[0] );
|
||||
|
||||
mData->mObjects.erase( mData->mObjects.begin() );
|
||||
}
|
||||
|
||||
mData->mObjects.insert( mData->mObjects.end(), withoutRegion.begin(), withoutRegion.end() );
|
||||
|
||||
mData->mPropTimer.start();
|
||||
if( vctSelection.size() )
|
||||
{
|
||||
LLSelectMgr::instance().enableBatchMode();
|
||||
mData->mSelection = LLSelectMgr::instance().selectObjectAndFamily( vctSelection );
|
||||
LLSelectMgr::instance().disableBatchMode();
|
||||
}
|
||||
}
|
||||
|
||||
U32 FSFloaterVRAMUsage::calcTexturSize( LLViewerObject *aObject, std::ostream *aTooltip )
|
||||
{
|
||||
if( !aObject || !aObject->mDrawable || aObject->mDrawable->isDead() )
|
||||
return 0;
|
||||
|
||||
std::map< LLUUID, U32 > stTextures;
|
||||
|
||||
F64 totalTexSize = 0;
|
||||
U8 numTEs = aObject->getNumTEs();
|
||||
|
||||
if (aTooltip )
|
||||
*aTooltip << (U32)numTEs << " TEs" << std::endl;
|
||||
|
||||
for( U8 j = 0; j < numTEs; ++j )
|
||||
{
|
||||
LLViewerTexture *pTex = aObject->getTEImage( j );
|
||||
if( !pTex || pTex->isMissingAsset() )
|
||||
continue;
|
||||
|
||||
U32 textureId = stTextures.size();
|
||||
bool bOldTexId( false );
|
||||
|
||||
if( stTextures.end() != stTextures.find( pTex->getID() ) )
|
||||
{
|
||||
textureId = stTextures[ pTex->getID() ];
|
||||
bOldTexId = true;
|
||||
}
|
||||
|
||||
if (aTooltip )
|
||||
*aTooltip << "TE: " << (U32)j << " tx: " << textureId << " w/h/c " << pTex->getFullWidth() << "/" << pTex->getFullHeight() << "/" << (U32)pTex->getComponents() << std::endl;
|
||||
|
||||
if( bOldTexId )
|
||||
continue;
|
||||
|
||||
stTextures[ pTex->getID() ] = textureId;
|
||||
|
||||
S32 texSize = pTex->getFullWidth() * pTex->getFullHeight() * pTex->getComponents();
|
||||
if( pTex->getUseMipMaps() )
|
||||
texSize += (texSize*33)/100;
|
||||
|
||||
totalTexSize += texSize;
|
||||
}
|
||||
|
||||
totalTexSize /= 1024.0;
|
||||
return static_cast< U32 >( totalTexSize );
|
||||
}
|
||||
|
||||
void FSFloaterVRAMUsage::doRefresh()
|
||||
{
|
||||
mData->mList->deleteAllItems();
|
||||
S32 numObjects = gObjectList.getNumObjects();
|
||||
|
||||
mData->mPending = 0;
|
||||
mData->mObjects.clear();
|
||||
LLSelectMgr::instance().deselectAll();
|
||||
|
||||
for( S32 i = 0; i < numObjects; ++i )
|
||||
{
|
||||
LLViewerObject *pObj = gObjectList.getObject( i );
|
||||
if( !pObj ) // Might be dead
|
||||
continue;
|
||||
|
||||
if( !pObj->mbCanSelect ||
|
||||
pObj->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ||
|
||||
pObj->getPCode() == LLViewerObject::LL_VO_SKY ||
|
||||
pObj->getPCode() == LLViewerObject::LL_VO_WL_SKY ||
|
||||
pObj->getPCode() == LLViewerObject::LL_VO_VOID_WATER ||
|
||||
pObj->getPCode() == LLViewerObject::LL_VO_WATER ||
|
||||
pObj->isAvatar() )
|
||||
continue;
|
||||
|
||||
// Exclude everything that's not in a sphere with r=draw distance around the avatar.
|
||||
F64 distance = (pObj->getPositionGlobal() - gAgentAvatarp->getPositionGlobal()).length();
|
||||
if( distance > gAgentCamera.mDrawDistance )
|
||||
continue;
|
||||
|
||||
ObjectStat oObject;
|
||||
oObject.mId = pObj->getID();
|
||||
oObject.mTextureSize = calcTexturSize( pObj );
|
||||
|
||||
mData->mObjects.push_back( oObject );
|
||||
}
|
||||
std::sort( mData->mObjects.begin(), mData->mObjects.end(), sortByTexture );
|
||||
}
|
||||
|
||||
void FSFloaterVRAMUsage::addObjectToList( LLViewerObject *aObject, std::string const &aName )
|
||||
{
|
||||
LLScrollListItem::Params item;
|
||||
|
||||
F64 distance = (aObject->getPositionGlobal() - gAgentAvatarp->getPositionGlobal()).length();
|
||||
|
||||
item.columns.add().column("uuid").value( aObject->getID() );
|
||||
item.columns.add().column("name").value( aName );
|
||||
item.columns.add().column("distance").value( distance );
|
||||
item.columns.add().column("faces").value( aObject->getNumFaces() );
|
||||
item.columns.add().column("vertices").value( static_cast<S32>( aObject->getNumVertices() ) );
|
||||
item.columns.add().column("indices").value( static_cast<S32>( aObject->getNumIndices() ) );
|
||||
|
||||
std::stringstream strTooltip;
|
||||
U32 totalTexSize = calcTexturSize( aObject, &strTooltip );
|
||||
|
||||
F64 totalVboSize(0.0);
|
||||
|
||||
LLPointer< LLDrawable > pDrawable = aObject->mDrawable;
|
||||
S32 numFaces = 0;
|
||||
if( pDrawable && !pDrawable->isDead() )
|
||||
numFaces = pDrawable->getNumFaces();
|
||||
|
||||
strTooltip << numFaces << " faces" << std::endl;
|
||||
for (S32 j = 0; j < numFaces; j++)
|
||||
{
|
||||
LLFace* pFace = pDrawable->getFace( j );
|
||||
if( !pFace )
|
||||
continue;
|
||||
|
||||
S32 cmW = 0, cmH = 0;
|
||||
|
||||
calcFaceSize( pFace, cmW, cmH );
|
||||
|
||||
strTooltip << "Face: " << j << " extends (cm) w/h " << cmW << "/" << cmH << std::endl;
|
||||
|
||||
S32 vertexSize = calcVBOEntrySize( pFace->getVertexBuffer() ) * aObject->getNumVertices();;
|
||||
S32 indexSize = sizeof( S16 ) * aObject->getNumIndices();
|
||||
|
||||
totalVboSize += vertexSize;
|
||||
totalVboSize += indexSize;
|
||||
}
|
||||
|
||||
totalVboSize /= 1024.0;
|
||||
|
||||
item.columns.add().column("vram_usage").value( (S32)totalTexSize );
|
||||
item.columns.add().column("vram_usage_vbo").value( (S32)totalVboSize );
|
||||
|
||||
LLScrollListItem *pRow = mData->mList->addRow( item );
|
||||
if( pRow )
|
||||
{
|
||||
for( S32 j = 0; j < pRow->getNumColumns(); ++j )
|
||||
pRow->getColumn( j )->setToolTip( strTooltip.str() );
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterVRAMUsage::calcFaceSize( LLFace *aFace, S32 &aW, S32 &aH )
|
||||
{
|
||||
aW = aH = 0;
|
||||
if( !aFace )
|
||||
return;
|
||||
|
||||
LLVector4a size;
|
||||
size.setSub( aFace->mExtents[1], aFace->mExtents[0] );
|
||||
|
||||
S32 cmX = static_cast<S32>( size[0]*100 );
|
||||
S32 cmY = static_cast<S32>( size[1]*100 );
|
||||
S32 cmZ = static_cast<S32>( size[2]*100 );
|
||||
|
||||
aW = cmX;
|
||||
aH = cmY;
|
||||
|
||||
if( 0 != cmZ )
|
||||
{
|
||||
if( 0 == aW )
|
||||
aW = cmZ;
|
||||
else
|
||||
aH = cmZ;
|
||||
}
|
||||
}
|
||||
|
||||
S32 FSFloaterVRAMUsage::calcVBOEntrySize( LLVertexBuffer *aVBO )
|
||||
{
|
||||
if( !aVBO )
|
||||
return 0;
|
||||
|
||||
S32 vboEntrySize(0);
|
||||
|
||||
U32 vboMask = aVBO->getTypeMask();
|
||||
for( S32 k = 0, l = 1; k < LLVertexBuffer::TYPE_MAX; ++k )
|
||||
{
|
||||
if( vboMask & l && k != LLVertexBuffer::TYPE_TEXTURE_INDEX )
|
||||
vboEntrySize += LLVertexBuffer::sTypeSize[ k ];
|
||||
l = l << 1;
|
||||
}
|
||||
|
||||
return vboEntrySize;
|
||||
}
|
||||
|
||||
void FSFloaterVRAMUsage::onProperties( LLSelectNode const *aProps )
|
||||
{
|
||||
if( !aProps && !aProps->getObject() )
|
||||
return;
|
||||
|
||||
LLUUID id = aProps->getObject()->getID();
|
||||
LLViewerObject *pObj = gObjectList.findObject( id );
|
||||
addObjectToList( pObj, aProps->mName );
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (c) 2015 Nicky Dasmijn
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef FS_FLOATERVRAMUSAGE_H
|
||||
#define FS_FLOATERVRAMUSAGE_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llselectmgr.h"
|
||||
|
||||
class LLScrollListCtrl;
|
||||
class LLViewerObject;
|
||||
class LLFace;
|
||||
class LLVertexBuffer;
|
||||
|
||||
class FSFloaterVRAMUsage : public LLFloater, public nd::selection::PropertiesListener
|
||||
{
|
||||
public:
|
||||
FSFloaterVRAMUsage(const LLSD& seed);
|
||||
/*virtual*/ ~FSFloaterVRAMUsage();
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
|
||||
BOOL postBuild();
|
||||
|
||||
virtual void onProperties( LLSelectNode const * );
|
||||
|
||||
void onIdle();
|
||||
|
||||
private:
|
||||
void doRefresh();
|
||||
|
||||
void addObjectToList( LLViewerObject*, std::string const& );
|
||||
void calcFaceSize( LLFace *aFace, S32 &aW, S32 &aH );
|
||||
S32 calcVBOEntrySize( LLVertexBuffer *aVBO );
|
||||
U32 calcTexturSize( LLViewerObject*, std::ostream * = 0 );
|
||||
|
||||
struct ImplData;
|
||||
ImplData *mData;
|
||||
};
|
||||
|
||||
#endif // FS_FLOATERBLOCKLIST_H
|
||||
|
|
@ -954,6 +954,23 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& po
|
|||
void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const
|
||||
{
|
||||
const LLMatrix4& vol_mat = getWorldMatrix();
|
||||
if( ! getViewerObject() )
|
||||
{
|
||||
LL_WARNS() << "No viewer object" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
if( ! getViewerObject()->getVolume() )
|
||||
{
|
||||
LL_WARNS() << "No volume" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( getViewerObject()->getVolume()->getNumVolumeFaces() <= mTEOffset )
|
||||
{
|
||||
LL_WARNS() << "No volume face" << (S32)mTEOffset << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
|
||||
const LLVector4a& normal4a = vf.mNormals[0];
|
||||
const LLVector4a& tangent = vf.mTangents[0];
|
||||
|
|
|
|||
|
|
@ -490,6 +490,9 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLV
|
|||
object->addThisAndNonJointChildren(objects);
|
||||
addAsFamily(objects);
|
||||
|
||||
if( isBatchMode() )
|
||||
continue;
|
||||
|
||||
// Stop the object from moving (this anticipates changes on the
|
||||
// simulator in LLTask::userSelect)
|
||||
object->setVelocity(LLVector3::zero);
|
||||
|
|
@ -498,6 +501,14 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLV
|
|||
object->resetRot();
|
||||
}
|
||||
|
||||
if( isBatchMode() )
|
||||
{
|
||||
mShowSelection = FALSE;
|
||||
sendSelect();
|
||||
return mSelectedObjects;
|
||||
}
|
||||
|
||||
|
||||
updateSelectionCenter();
|
||||
saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
|
||||
updatePointAt();
|
||||
|
|
@ -5343,6 +5354,10 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
|
|||
node->mInventorySerial = inv_serial;
|
||||
node->mSitName.assign(sit_name);
|
||||
node->mTouchName.assign(touch_name);
|
||||
|
||||
// <FS:ND> Fire for any observer interested in object properties
|
||||
LLSelectMgr::instance().firePropertyReceived( node );
|
||||
// </FS:ND>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,11 @@ protected:
|
|||
LLPointer<LLViewerObject> mObject;
|
||||
S32 mTESelectMask;
|
||||
S32 mLastTESelected;
|
||||
|
||||
// <FS:ND> For const access. Need to check for isDead yourself.
|
||||
public:
|
||||
LLViewerObject const* getObject() const { return mObject; }
|
||||
// </FS:ND>
|
||||
};
|
||||
|
||||
class LLObjectSelection : public LLRefCount
|
||||
|
|
@ -397,7 +402,47 @@ extern template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance()
|
|||
// For use with getFirstTest()
|
||||
struct LLSelectGetFirstTest;
|
||||
|
||||
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
|
||||
// <FS:ND> To listened into received prop. messages
|
||||
namespace nd
|
||||
{
|
||||
namespace selection
|
||||
{
|
||||
class PropertiesListener
|
||||
{
|
||||
public:
|
||||
virtual void onProperties( LLSelectNode const * ) = 0;
|
||||
};
|
||||
|
||||
class PropertiesServer
|
||||
{
|
||||
public:
|
||||
PropertiesServer()
|
||||
: mBatchMode( false )
|
||||
{ }
|
||||
|
||||
void registerPropertyListener( nd::selection::PropertiesListener *aP) { mListener.insert( aP ); }
|
||||
void removePropertyListener( nd::selection::PropertiesListener *aP) { mListener.erase( aP ); }
|
||||
|
||||
void enableBatchMode( ) { mBatchMode = true; }
|
||||
void disableBatchMode( ) { mBatchMode = false; }
|
||||
bool isBatchMode() const { return mBatchMode; }
|
||||
|
||||
protected:
|
||||
void firePropertyReceived( LLSelectNode const *aNode )
|
||||
{
|
||||
for( std::set< nd::selection::PropertiesListener * >::iterator itr = mListener.begin(); itr != mListener.end(); ++itr )
|
||||
(*itr)->onProperties( aNode );
|
||||
}
|
||||
|
||||
private:
|
||||
std::set< nd::selection::PropertiesListener * > mListener;
|
||||
bool mBatchMode;
|
||||
};
|
||||
}
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>, public nd::selection::PropertiesServer
|
||||
{
|
||||
public:
|
||||
static BOOL sRectSelectInclusive; // do we need to surround an object to pick it?
|
||||
|
|
|
|||
|
|
@ -187,6 +187,9 @@
|
|||
#include "NACLfloaterexploresounds.h"
|
||||
#include "particleeditor.h"
|
||||
#include "quickprefs.h"
|
||||
|
||||
#include "fsfloatervramusage.h"
|
||||
|
||||
// handle secondlife:///app/openfloater/{NAME} URLs
|
||||
class LLFloaterOpenHandler : public LLCommandHandler
|
||||
{
|
||||
|
|
@ -427,5 +430,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("sound_explorer", "floater_NACL_explore_sounds.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<NACLFloaterExploreSounds>);
|
||||
LLFloaterReg::add("ws_asset_blacklist", "floater_asset_blacklist.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterWSAssetBlacklist>);
|
||||
|
||||
LLFloaterReg::add( "vram_usage", "fs_floater_vram_usage.xml", static_cast<LLFloaterBuildFunc>( &LLFloaterReg::build< FSFloaterVRAMUsage >) );
|
||||
|
||||
LLFloaterReg::registerControlVariables(); // Make sure visibility and rect controls get preserved when saving
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater
|
||||
positioning="centered"
|
||||
legacy_header_height="18"
|
||||
can_resize="true"
|
||||
default_tab_group="1"
|
||||
height="350"
|
||||
layout="topleft"
|
||||
min_height="160"
|
||||
min_width="270"
|
||||
name="object_vram_usage"
|
||||
help_topic=""
|
||||
save_rect="true"
|
||||
title="Object impact on VRAM"
|
||||
width="400">
|
||||
<scroll_list
|
||||
name="result_list"
|
||||
left="10"
|
||||
right="-10"
|
||||
top="14"
|
||||
bottom="-32"
|
||||
follows="left|top|bottom|right"
|
||||
can_resize="true"
|
||||
column_padding="0"
|
||||
draw_heading="true"
|
||||
multi_select="false"
|
||||
search_column="6">
|
||||
<column
|
||||
name="uuid"
|
||||
label="uuid"
|
||||
width="0"/>
|
||||
<column
|
||||
name="name"
|
||||
label="Name"
|
||||
dynamicwidth="true"/>
|
||||
<column
|
||||
name="distance"
|
||||
label="Distance"
|
||||
dynamicwidth="true"/>
|
||||
<column
|
||||
name="faces"
|
||||
label="Faces"
|
||||
dynamicwidth="true"/>
|
||||
<column
|
||||
name="vertices"
|
||||
label="Vertices"
|
||||
dynamicwidth="true"/>
|
||||
<column
|
||||
name="indices"
|
||||
label="Indices"
|
||||
dynamicwidth="true"/>
|
||||
<column
|
||||
name="vram_usage"
|
||||
label="VRAM (Textures) in kb"
|
||||
dynamicwidth="true"/>
|
||||
<column
|
||||
name="vram_usage_vbo"
|
||||
label="VRAM (VBO) in kb"
|
||||
dynamicwidth="true"/>
|
||||
</scroll_list>
|
||||
<button
|
||||
follows="bottom|left"
|
||||
left="10"
|
||||
top="-25"
|
||||
height="23"
|
||||
label="Refresh"
|
||||
label_selected="Refresh"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
name="refresh_button"
|
||||
width="120">
|
||||
</button>
|
||||
</floater>
|
||||
|
|
@ -3287,6 +3287,13 @@
|
|||
function="ToggleControl"
|
||||
parameter="DebugShowTextureInfo" />
|
||||
</menu_item_check>
|
||||
<menu_item_call
|
||||
label="VRAM usage per object"
|
||||
name="VRAM usage per object">
|
||||
<menu_item_call.on_click
|
||||
function="Floater.Show"
|
||||
parameter="vram_usage" />
|
||||
</menu_item_call>
|
||||
<menu_item_check
|
||||
label="Show Avatar Render Info"
|
||||
name="Show Avatar Render Info">
|
||||
|
|
|
|||
Loading…
Reference in New Issue