FIRE-14264; FPS drop due to particle patch.

Nicky 2014-08-02 14:57:53 +02:00
parent 16abc303d0
commit cdb30d7498
9 changed files with 23 additions and 423 deletions

View File

@ -186,7 +186,6 @@ set(viewer_SOURCE_FILES
fsradarmenu.cpp
fsscriptlibrary.cpp
fsslurlcommand.cpp
fsvopartgroup.cpp
fswsassetblacklist.cpp
groupchatlistener.cpp
#growlmanager.cpp
@ -890,7 +889,6 @@ set(viewer_HEADER_FILES
fsscriptlibrary.h
fsslurl.h
fsslurlcommand.h
fsvopartgroup.h
fswsassetblacklist.h
groupchatlistener.h
llaccountingcost.h

View File

@ -1,112 +0,0 @@
/**
* @file fsvopartgroup.cpp
* @brief fsvopartgroup base class
*
* $LicenseInfo:firstyear=2014&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2014, The Phoenix Firestorm Project, 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
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llviewerpartsim.h" // For LL_MAX_PARTICLE_COUNT
#include "fsvopartgroup.h"
FSVOPartGroup::FSVOPartGroup()
{
for (S32 i = 0; i < sFreeIndexSize; ++i)
{
setFreeIndex(i, 0);
}
setIndexGeneration(1);
setTotalParticles(0);
U32 bitMasksTmp[ 32 ] = { 0xFFFFFFFF, 0x80000000, 0xC0000000, 0xE0000000,
0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000,
0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000,
0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0,
0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE };
for (S32 i = 0; i < 32; ++i)
{
bitMasks[i] = bitMasksTmp[i];
}
}
bool FSVOPartGroup::findAvailableVBSlots( S32 &idxStart, S32 &idxEnd, U32 amount )
{
idxStart = idxEnd = -1;
if( amount + getTotalParticles() > LL_MAX_PARTICLE_COUNT )
amount = LL_MAX_PARTICLE_COUNT - getTotalParticles();
U32 u32Count = amount/32;
U32 bitsLeft = amount - (u32Count*32);
if( bitsLeft )
++u32Count;
U32 maskLast = bitMasks[ bitsLeft ];
int i = 0;
int maxI = LL_MAX_PARTICLE_COUNT/32-u32Count;
do
{
while( getFreeIndex(i) != 0xFFFFFFFF && i <= maxI )
++i;
if( i > maxI )
continue;
int j = i;
while( getFreeIndex(j) == 0xFFFFFFFF && j <= LL_MAX_PARTICLE_COUNT/32 && (j-i) != u32Count )
++j;
if( j > LL_MAX_PARTICLE_COUNT/32 || (i-j) != u32Count || (getFreeIndex(j-1) & maskLast) != maskLast )
{
++i;
continue;
}
int k = 0;
idxStart = i*32;
idxEnd = i + amount;
while( k != amount )
{
for( int l = 0; k != amount && l < 32; ++l )
{
U32 mask = 1 << l;
setFreeIndex(i, getFreeIndex(i) & ~mask);
++k;
}
++i;
}
setTotalParticles(getTotalParticles() + amount);
return true;
} while( i <= maxI);
return false;
}

View File

@ -1,58 +0,0 @@
/**
* @file fsvopartgroup.h
* @brief fsvopartgroup base class
*
* $LicenseInfo:firstyear=2014&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2014, The Phoenix Firestorm Project, 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
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#ifndef FS_VOPARTGROUP_H
#define FS_VOPARTGROUP_H
#include "stdtypes.h"
#define sFreeIndexSize LL_MAX_PARTICLE_COUNT/32
class FSVOPartGroup
{
public:
FSVOPartGroup();
~FSVOPartGroup() {};
U32 getFreeIndex(int i) {return sFreeIndex[i];}
U32 getIndexGeneration() {return sIndexGeneration;}
U32 getTotalParticles() {return sTotalParticles;}
void setFreeIndex(int i, U32 val) {sFreeIndex[i] = val;}
void setIndexGeneration(U32 val) {sIndexGeneration = val;}
void setTotalParticles(U32 val) {sTotalParticles = val;}
bool findAvailableVBSlots( S32 &idxStart, S32 &idxEnd, U32 amount );
private:
U32 sFreeIndex[sFreeIndexSize];
U32 sIndexGeneration;
U32 sTotalParticles;
U32 bitMasks[ 32 ];
};
#endif // FS_VOPARTGROUP_H

View File

@ -166,8 +166,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mBoundingSphereRadius = 0.0f ;
mHasMedia = FALSE ;
mParticleGeneration = 0; // <FS:ND/> Default = no particle
}
void LLFace::destroy()
@ -185,14 +183,9 @@ void LLFace::destroy()
}
}
// <FS:ND> Make sure we released any allocated VB index if this was a particle
// if (isState(LLFace::PARTICLE))
if (isState(LLFace::PARTICLE) || mParticleGeneration )
// </FS:ND>
if (isState(LLFace::PARTICLE))
{
LLVOPartGroup::freeVBSlot(getGeomIndex()/4,mParticleGeneration);
mParticleGeneration = 0;
LLVOPartGroup::freeVBSlot(getGeomIndex()/4);
clearState(LLFace::PARTICLE);
}
@ -421,16 +414,8 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
llassert(verify());
}
// <FS:ND> Pass another flag to mark this index as from LLVOPartGroup, in that case it needs to be freed with LLVOPartGroup::LLVOPartGroup
// void LLFace::setGeomIndex(U16 idx)
void LLFace::setGeomIndex(U16 idx, U32 aParticleGeneration )
// </FS:ND>
void LLFace::setGeomIndex(U16 idx)
{
if( mParticleGeneration && mGeomIndex != idx )
LLVOPartGroup::freeVBSlot(getGeomIndex()/4,mParticleGeneration);
mParticleGeneration = aParticleGeneration;
if (mGeomIndex != idx)
{
mGeomIndex = idx;

View File

@ -207,11 +207,7 @@ public:
BOOL verify(const U32* indices_array = NULL) const;
void printDebugInfo() const;
// <FS:ND> Pass another flag to mark this index as from LLVOPartGroup, in that case it needs to be freed with LLVOPartGroup::LLVOPartGroup
// void setGeomIndex(U16 idx);
void setGeomIndex(U16 idx, U32 aParticleGeneration = 0);
// </FS:ND>
void setGeomIndex(U16 idx);
void setIndicesIndex(S32 idx);
void setDrawInfo(LLDrawInfo* draw_info);
@ -363,9 +359,6 @@ public:
lhs->getTexture() < rhs->getTexture();
}
};
private:
U32 mParticleGeneration;
};
#endif // LL_LLFACE_H

View File

@ -284,36 +284,16 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
LLViewerCamera* camera = LLViewerCamera::getInstance();
LLViewerRegion *regionp = getRegion();
S32 end = (S32) mParticles.size();
// <FS:ND> Instead of walking the current particles back to front, we first make a copy, then sort by adress and refill mParticles as needed.
mParticlesTemp.swap( mParticles );
mParticles.erase( mParticles.begin(), mParticles.end() );
std::sort( mParticlesTemp.begin(), mParticlesTemp.end() );
// for (S32 i = 0 ; i < (S32)mParticles.size(); )
for (S32 i = 0 ; i < (S32)mParticlesTemp.size(); ++i )
// </FS:ND>
for (S32 i = 0 ; i < (S32)mParticles.size();)
{
// LLVector3 a(0.f, 0.f, 0.f); // <FS:ND/> Unused
LLViewerPart* part = mParticlesTemp[i] ;
LLVector3 a(0.f, 0.f, 0.f);
LLViewerPart* part = mParticles[i] ;
dt = lastdt + mSkippedTime - part->mSkipOffset;
part->mSkipOffset = 0.f;
// Update current time
const F32 cur_time = part->mLastUpdateTime + dt;
// <FS:ND> Bail out as soon as possible to avoid all the complicated work down.
if( cur_time > part->mMaxAge || LLViewerPart::LL_PART_DEAD_MASK == part->mFlags )
{
if (part->mVPCallback)
(*part->mVPCallback)(*part, dt);
delete part ;
continue;
}
// </FS:ND>
const F32 frac = cur_time / part->mMaxAge;
// "Drift" the object based on the source object
@ -417,34 +397,26 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
part->mLastUpdateTime = cur_time;
// <FS:ND> We did that above
// Kill dead particles (either flagged dead, or too old)
// if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags))
// {
// mParticles[i] = mParticles.back() ;
// mParticles.pop_back() ;
// delete part ;
// }
// else
// </FS:ND>
if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags))
{
mParticles[i] = mParticles.back() ;
mParticles.pop_back() ;
delete part ;
}
else
{
F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale);
if (!posInGroup(part->mPosAgent, desired_size))
{
// Transfer particles between groups
LLViewerPartSim::getInstance()->put(part) ;
// <FS:ND> No need for any transfer, just to not add to mParticles.
// mParticles[i] = mParticles.back() ;
// mParticles.pop_back() ;
// </FS:ND>
mParticles[i] = mParticles.back() ;
mParticles.pop_back() ;
}
else
{
// <FS:ND> Keep current particle in this group.
// i++ ;
mParticles.push_back( part );
// </FS:ND>
i++ ;
}
}
}
@ -920,76 +892,3 @@ void LLViewerPartSim::clearParticlesByOwnerID(const LLUUID& task_id)
}
}
// <FS:ND> Object pool for LLViewerPart
U8 *sParts;
U8 *sPartsEnd;
U32 sFree[ LL_MAX_PARTICLE_COUNT/32 ];
U32 sPartSize;
S32 findFreeIndex()
{
for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
{
if( sFree[i] )
{
U32 val = sFree[i];
U32 mask = 1;
int j(0);
for( j = 0; j < 32; ++j )
{
if( mask & val )
{
mask = ~mask;
break;
}
mask <<= 1;
}
sFree[ i ] = val & mask;
return i*32+j;
}
}
return -1;
}
void* LLViewerPart::operator new(size_t size)
{
if( !sParts )
{
sPartSize = sizeof( LLViewerPart );
sPartSize += 0xF;
sPartSize &= ~0xF;
sParts = reinterpret_cast<U8*>( ll_aligned_malloc<16>( sPartSize * LL_MAX_PARTICLE_COUNT ) );
for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
sFree[ i ] = 0xFFFFFFFF;
sPartsEnd = sParts + sPartSize * LL_MAX_PARTICLE_COUNT;
}
S32 i = findFreeIndex();
if( i < 0 )
return new char[ size ];
return reinterpret_cast< void* >( sParts + sPartSize*i );
}
void LLViewerPart::operator delete(void* ptr)
{
if( ptr < sParts || ptr >= sPartsEnd )
{
delete [] (char*)ptr;
return;
}
U32 diff = static_cast<U32>( reinterpret_cast<U8*>(ptr) - sParts );
diff /= sPartSize;
U32 i = (diff & ~0x0000001F) / 32;
U32 j = diff & 0x0000001F;
U32 mask = 1 << j;
sFree[ i ] |= mask;
}
// </FS:ND>

View File

@ -81,10 +81,6 @@ public:
static U32 sNextPartID;
// <FS:ND> Object pool for LLViewerPart
void* operator new(size_t size);
void operator delete(void* ptr);
// </FS:ND>
};
@ -112,7 +108,6 @@ public:
typedef std::vector<LLViewerPart*> part_list_t;
part_list_t mParticles;
part_list_t mParticlesTemp; // <FS:ND/> Temporary list for iteration in updateParticles
const LLVector3 &getCenterAgent() const { return mCenterAgent; }
S32 getCount() const { return (S32) mParticles.size(); }

View File

@ -51,9 +51,6 @@ extern U64MicrosecondsImplicit gFrameTime;
LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL;
S32 LLVOPartGroup::sVBSlotCursor = 0;
#include "fsvopartgroup.h" //<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
FSVOPartGroup *LLVOPartGroup::fsvopartgroup = NULL;
void LLVOPartGroup::initClass()
{
@ -62,16 +59,6 @@ void LLVOPartGroup::initClass()
//static
void LLVOPartGroup::restoreGL()
{
if (fsvopartgroup == NULL)
{
fsvopartgroup = new FSVOPartGroup();
}
//<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
fsvopartgroup->setIndexGeneration( fsvopartgroup->getIndexGeneration() + 2);
for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
fsvopartgroup->setFreeIndex(i, 0xFFFFFFFF);
//</FS:LO>
//TODO: optimize out binormal mask here. Specular and normal coords as well.
sVB = new LLVertexBuffer(VERTEX_DATA_MASK | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, GL_STREAM_DRAW_ARB);
@ -131,41 +118,12 @@ void LLVOPartGroup::destroyGL()
//static
S32 LLVOPartGroup::findAvailableVBSlot()
{
//<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
/*if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)
if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)
{ //no more available slots
return -1;
}
return sVBSlotCursor++;*/
for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
{
if( fsvopartgroup->getFreeIndex(i) != 0 )
{
U32 val = fsvopartgroup->getFreeIndex(i);
U32 mask = 1;
int j(0);
for( j = 0; j < 32; ++j )
{
if( mask & val )
{
mask = ~mask;
break;
}
mask <<= 1;
}
fsvopartgroup->setFreeIndex(i, val & mask);
fsvopartgroup->setTotalParticles(fsvopartgroup->getTotalParticles()+1);
return i*32+j;
}
}
return -1;
//</FS:LO>
return sVBSlotCursor++;
}
bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
@ -184,9 +142,7 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
}
//static
//<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
// void LLVOPartGroup::freeVBSlot(S32 idx)
void LLVOPartGroup::freeVBSlot(S32 idx, U32 generation )
void LLVOPartGroup::freeVBSlot(S32 idx)
{
/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
//llassert(sVBSlotCursor > sVBSlotFree);
@ -197,23 +153,6 @@ void LLVOPartGroup::freeVBSlot(S32 idx, U32 generation )
sVBSlotCursor--;
*sVBSlotCursor = idx;
}*/
if( idx < 0 || idx >= LL_MAX_PARTICLE_COUNT )
return;
//<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
fsvopartgroup->setTotalParticles(fsvopartgroup->getTotalParticles()-1);
if( fsvopartgroup->getIndexGeneration() != generation )
return;
U32 i = (idx & ~0x0000001F) / 32;
U32 j = idx & 0x0000001F;
U32 mask = 1 << j;
fsvopartgroup->setFreeIndex(i, fsvopartgroup->getFreeIndex(i) | mask);
//</FS:LO>
}
LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
@ -223,10 +162,6 @@ LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegi
setNumTEs(1);
setTETexture(0, LLUUID::null);
mbCanSelect = FALSE; // users can't select particle systems
if (fsvopartgroup == NULL)
{
fsvopartgroup = new FSVOPartGroup();
}
}
@ -924,14 +859,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
// <FS:ND> Free all vb slots. Then try to allocate an adjacent block of slots for all faces
for( std::vector<LLFace*>::iterator itr = mFaceList.begin(); itr != mFaceList.end(); ++itr )
(*itr)->setGeomIndex( 0 );
S32 idxStart, idxEnd;
bool bValidRange = LLVOPartGroup::getFsvopartgroup()->findAvailableVBSlots( idxStart, idxEnd, mFaceList.size() );
// </FS:ND>
for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
{
LLFace* facep = *i;
@ -939,26 +866,10 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
//if (!facep->isState(LLFace::PARTICLE))
{ //set the indices of this face
// <FS:ND> Can we use a index from our preallocated list?
// S32 idx = LLVOPartGroup::findAvailableVBSlot();
S32 idx(-1);
if( bValidRange )
{
if( idxStart < idxEnd )
idx = idxStart++;
}
else
idx = LLVOPartGroup::findAvailableVBSlot();
// </FS:ND>
S32 idx = LLVOPartGroup::findAvailableVBSlot();
if (idx >= 0)
{
// <FS:ND> Face needs to release the index when it gets destroyed.
// facep->setGeomIndex(idx*4);
facep->setGeomIndex(idx*4, LLVOPartGroup::getFsvopartgroup()->getIndexGeneration());
// </FS:ND>
facep->setGeomIndex(idx*4);
facep->setIndicesIndex(idx*6);
facep->setVertexBuffer(LLVOPartGroup::sVB);
facep->setPoolType(LLDrawPool::POOL_ALPHA);

View File

@ -36,8 +36,6 @@
class LLViewerPartGroup;
class FSVOPartGroup; //<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
class LLVOPartGroup : public LLAlphaObject
{
public:
@ -50,9 +48,7 @@ public:
static void restoreGL();
static void destroyGL();
static S32 findAvailableVBSlot();
// static void freeVBSlot(S32 idx);
static void freeVBSlot(S32 idx, U32 generation);
static void freeVBSlot(S32 idx);
enum
{
@ -108,8 +104,6 @@ public:
void setViewerPartGroup(LLViewerPartGroup *part_groupp) { mViewerPartGroupp = part_groupp; }
LLViewerPartGroup* getViewerPartGroup() { return mViewerPartGroupp; }
static FSVOPartGroup* getFsvopartgroup() {return fsvopartgroup;}//<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
protected:
~LLVOPartGroup();
@ -117,11 +111,6 @@ protected:
virtual LLVector3 getCameraPosition() const;
//<FS:LO> Fixing up/classifying Nicky D's fsvopartgroup code
private:
static FSVOPartGroup* fsvopartgroup;
//</FS:LO>
};