Automated merge with ssh://hg.lindenlab.com/richard/viewer-interesting
commit
774544bc51
|
|
@ -1417,18 +1417,7 @@ bool LLAppViewer::mainLoop()
|
|||
S32 io_pending = 0;
|
||||
F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
|
||||
|
||||
{
|
||||
LLFastTimer ftm(FTM_TEXTURE_CACHE);
|
||||
work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
|
||||
}
|
||||
{
|
||||
LLFastTimer ftm(FTM_DECODE);
|
||||
work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
|
||||
}
|
||||
{
|
||||
LLFastTimer ftm(FTM_DECODE);
|
||||
work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
|
||||
}
|
||||
work_pending += updateTextureThreads(max_time);
|
||||
|
||||
{
|
||||
LLFastTimer ftm(FTM_VFS);
|
||||
|
|
@ -1546,6 +1535,24 @@ bool LLAppViewer::mainLoop()
|
|||
return true;
|
||||
}
|
||||
|
||||
S32 LLAppViewer::updateTextureThreads(F32 max_time)
|
||||
{
|
||||
S32 work_pending = 0;
|
||||
{
|
||||
LLFastTimer ftm(FTM_TEXTURE_CACHE);
|
||||
work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
|
||||
}
|
||||
{
|
||||
LLFastTimer ftm(FTM_DECODE);
|
||||
work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
|
||||
}
|
||||
{
|
||||
LLFastTimer ftm(FTM_DECODE);
|
||||
work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
|
||||
}
|
||||
return work_pending;
|
||||
}
|
||||
|
||||
void LLAppViewer::flushVFSIO()
|
||||
{
|
||||
while (1)
|
||||
|
|
|
|||
|
|
@ -171,7 +171,8 @@ public:
|
|||
|
||||
void purgeCache(); // Clear the local cache.
|
||||
void purgeCacheImmediate(); //clear local cache immediately.
|
||||
|
||||
S32 updateTextureThreads(F32 max_time);
|
||||
|
||||
// mute/unmute the system's master audio
|
||||
virtual void setMasterSystemAudioMute(bool mute);
|
||||
virtual bool getMasterSystemAudioMute();
|
||||
|
|
|
|||
|
|
@ -1145,7 +1145,7 @@ LLSpatialBridge::~LLSpatialBridge()
|
|||
LLSpatialGroup* group = getSpatialGroup();
|
||||
if (group)
|
||||
{
|
||||
group->mSpatialPartition->remove(this, group);
|
||||
group->getSpatialPartition()->remove(this, group);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
|
|||
for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
|
||||
{
|
||||
LLSpatialGroup* group = *i;
|
||||
if (group->mSpatialPartition->mRenderByGroup &&
|
||||
if (group->getSpatialPartition()->mRenderByGroup &&
|
||||
!group->isDead())
|
||||
{
|
||||
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
|
||||
|
|
@ -389,15 +389,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||
{
|
||||
LLSpatialGroup* group = *i;
|
||||
llassert(group);
|
||||
llassert(group->mSpatialPartition);
|
||||
llassert(group->getSpatialPartition());
|
||||
|
||||
if (group->mSpatialPartition->mRenderByGroup &&
|
||||
if (group->getSpatialPartition()->mRenderByGroup &&
|
||||
!group->isDead())
|
||||
{
|
||||
bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow.
|
||||
// All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress.
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
|
||||
group->getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
|
||||
group->getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
|
||||
|
||||
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ void LLSceneMonitor::reset()
|
|||
|
||||
if(mQueryObject > 0)
|
||||
{
|
||||
release_occlusion_query_object_name(mQueryObject);
|
||||
LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(mQueryObject);
|
||||
mQueryObject = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -421,7 +421,7 @@ void LLSceneMonitor::calcDiffAggregate()
|
|||
|
||||
if(!mQueryObject)
|
||||
{
|
||||
mQueryObject = get_new_occlusion_query_object_name();
|
||||
mQueryObject = LLOcclusionCullingGroup::getNewOcclusionQueryObjectName();
|
||||
}
|
||||
|
||||
LLGLDepthTest depth(true, false, GL_ALWAYS);
|
||||
|
|
|
|||
|
|
@ -51,32 +51,16 @@
|
|||
#include "llvoavatar.h"
|
||||
#include "llvolumemgr.h"
|
||||
#include "lltextureatlas.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llviewershadermgr.h"
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
|
||||
static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound Partition");
|
||||
|
||||
const F32 SG_OCCLUSION_FUDGE = 0.25f;
|
||||
#define SG_DISCARD_TOLERANCE 0.01f
|
||||
|
||||
#if LL_OCTREE_PARANOIA_CHECK
|
||||
#define assert_octree_valid(x) x->validate()
|
||||
#define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates()
|
||||
#else
|
||||
#define assert_octree_valid(x)
|
||||
#define assert_states_valid(x)
|
||||
#endif
|
||||
|
||||
extern bool gShiftFrame;
|
||||
|
||||
static U32 sZombieGroups = 0;
|
||||
U32 LLSpatialGroup::sNodeCount = 0;
|
||||
|
||||
#define LL_TRACK_PENDING_OCCLUSION_QUERIES 0
|
||||
|
||||
std::set<GLuint> LLSpatialGroup::sPendingQueries;
|
||||
|
||||
U32 gOctreeMaxCapacity;
|
||||
|
||||
BOOL LLSpatialGroup::sNoDelete = FALSE;
|
||||
|
|
@ -84,57 +68,6 @@ BOOL LLSpatialGroup::sNoDelete = FALSE;
|
|||
static F32 sLastMaxTexPriority = 1.f;
|
||||
static F32 sCurMaxTexPriority = 1.f;
|
||||
|
||||
class LLOcclusionQueryPool : public LLGLNamePool
|
||||
{
|
||||
public:
|
||||
LLOcclusionQueryPool()
|
||||
{
|
||||
mCurQuery = 1;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::list<GLuint> mAvailableName;
|
||||
GLuint mCurQuery;
|
||||
|
||||
virtual GLuint allocateName()
|
||||
{
|
||||
GLuint ret = 0;
|
||||
|
||||
if (!mAvailableName.empty())
|
||||
{
|
||||
ret = mAvailableName.front();
|
||||
mAvailableName.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = mCurQuery++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual void releaseName(GLuint name)
|
||||
{
|
||||
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
|
||||
LLSpatialGroup::sPendingQueries.erase(name);
|
||||
#endif
|
||||
llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end());
|
||||
mAvailableName.push_back(name);
|
||||
}
|
||||
};
|
||||
|
||||
static LLOcclusionQueryPool sQueryPool;
|
||||
|
||||
GLuint get_new_occlusion_query_object_name()
|
||||
{
|
||||
return sQueryPool.allocate();
|
||||
}
|
||||
|
||||
void release_occlusion_query_object_name(GLuint name)
|
||||
{
|
||||
sQueryPool.release(name);
|
||||
}
|
||||
|
||||
//static counter for frame to switch LOD on
|
||||
|
||||
|
|
@ -148,97 +81,6 @@ void sg_assert(BOOL expr)
|
|||
#endif
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
b000 = 0x00,
|
||||
b001 = 0x01,
|
||||
b010 = 0x02,
|
||||
b011 = 0x03,
|
||||
b100 = 0x04,
|
||||
b101 = 0x05,
|
||||
b110 = 0x06,
|
||||
b111 = 0x07,
|
||||
} eLoveTheBits;
|
||||
|
||||
//contact Runitai Linden for a copy of the SL object used to write this table
|
||||
//basically, you give the table a bitmask of the look-at vector to a node and it
|
||||
//gives you a triangle fan index array
|
||||
static U16 sOcclusionIndices[] =
|
||||
{
|
||||
//000
|
||||
b111, b110, b010, b011, b001, b101, b100, b110,
|
||||
//001
|
||||
b011, b010, b000, b001, b101, b111, b110, b010,
|
||||
//010
|
||||
b101, b100, b110, b111, b011, b001, b000, b100,
|
||||
//011
|
||||
b001, b000, b100, b101, b111, b011, b010, b000,
|
||||
//100
|
||||
b110, b000, b010, b011, b111, b101, b100, b000,
|
||||
//101
|
||||
b010, b100, b000, b001, b011, b111, b110, b100,
|
||||
//110
|
||||
b100, b010, b110, b111, b101, b001, b000, b010,
|
||||
//111
|
||||
b000, b110, b100, b101, b001, b011, b010, b110,
|
||||
};
|
||||
|
||||
U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center)
|
||||
{
|
||||
LLVector4a origin;
|
||||
origin.load3(camera->getOrigin().mV);
|
||||
|
||||
S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7;
|
||||
|
||||
return cypher*8;
|
||||
}
|
||||
|
||||
U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center)
|
||||
{
|
||||
LLVector4a origin;
|
||||
origin.load3(camera->getOrigin().mV);
|
||||
|
||||
S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7;
|
||||
|
||||
return (U8*) (sOcclusionIndices+cypher*8);
|
||||
}
|
||||
|
||||
//create a vertex buffer for efficiently rendering cubes
|
||||
LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage)
|
||||
{
|
||||
LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage);
|
||||
|
||||
ret->allocateBuffer(8, 64, true);
|
||||
|
||||
LLStrider<LLVector3> pos;
|
||||
LLStrider<U16> idx;
|
||||
|
||||
ret->getVertexStrider(pos);
|
||||
ret->getIndexStrider(idx);
|
||||
|
||||
pos[0] = LLVector3(-1,-1,-1);
|
||||
pos[1] = LLVector3(-1,-1, 1);
|
||||
pos[2] = LLVector3(-1, 1,-1);
|
||||
pos[3] = LLVector3(-1, 1, 1);
|
||||
pos[4] = LLVector3( 1,-1,-1);
|
||||
pos[5] = LLVector3( 1,-1, 1);
|
||||
pos[6] = LLVector3( 1, 1,-1);
|
||||
pos[7] = LLVector3( 1, 1, 1);
|
||||
|
||||
for (U32 i = 0; i < 64; i++)
|
||||
{
|
||||
idx[i] = sOcclusionIndices[i];
|
||||
}
|
||||
|
||||
ret->flush();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion");
|
||||
|
||||
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
|
||||
|
||||
//returns:
|
||||
// 0 if sphere and AABB are not intersecting
|
||||
// 1 if they are
|
||||
|
|
@ -285,18 +127,7 @@ LLSpatialGroup::~LLSpatialGroup()
|
|||
sZombieGroups--;
|
||||
}
|
||||
|
||||
sNodeCount--;
|
||||
|
||||
if (gGLManager.mHasOcclusionQuery)
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
|
||||
{
|
||||
if (mOcclusionQuery[i])
|
||||
{
|
||||
release_occlusion_query_object_name(mOcclusionQuery[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
sNodeCount--;
|
||||
|
||||
clearDrawMap();
|
||||
clearAtlasList() ;
|
||||
|
|
@ -431,7 +262,7 @@ void LLSpatialGroup::clearDrawMap()
|
|||
|
||||
BOOL LLSpatialGroup::isHUDGroup()
|
||||
{
|
||||
return mSpatialPartition && mSpatialPartition->isHUDPartition() ;
|
||||
return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ;
|
||||
}
|
||||
|
||||
BOOL LLSpatialGroup::isRecentlyVisible() const
|
||||
|
|
@ -461,7 +292,7 @@ void LLSpatialGroup::validate()
|
|||
sg_assert(drawable->getSpatialGroup() == this);
|
||||
if (drawable->getSpatialBridge())
|
||||
{
|
||||
sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge());
|
||||
sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge());
|
||||
}
|
||||
|
||||
/*if (drawable->isSpatialBridge())
|
||||
|
|
@ -501,14 +332,6 @@ void LLSpatialGroup::validate()
|
|||
#endif
|
||||
}
|
||||
|
||||
void LLSpatialGroup::checkStates()
|
||||
{
|
||||
#if LL_OCTREE_PARANOIA_CHECK
|
||||
//LLOctreeStateCheck checker;
|
||||
//checker.traverse(mOctreeNode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLSpatialGroup::validateDrawMap()
|
||||
{
|
||||
#if LL_OCTREE_PARANOIA_CHECK
|
||||
|
|
@ -574,7 +397,7 @@ void LLSpatialGroup::rebuildGeom()
|
|||
{
|
||||
if (!isDead())
|
||||
{
|
||||
mSpatialPartition->rebuildGeom(this);
|
||||
getSpatialPartition()->rebuildGeom(this);
|
||||
|
||||
if (hasState(LLSpatialGroup::MESH_DIRTY))
|
||||
{
|
||||
|
|
@ -587,7 +410,7 @@ void LLSpatialGroup::rebuildMesh()
|
|||
{
|
||||
if (!isDead())
|
||||
{
|
||||
mSpatialPartition->rebuildMesh(this);
|
||||
getSpatialPartition()->rebuildMesh(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -665,23 +488,7 @@ void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
|
|||
|
||||
LLSpatialGroup* LLSpatialGroup::getParent()
|
||||
{
|
||||
if (isDead())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!mOctreeNode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
OctreeNode* parent = mOctreeNode->getOctParent();
|
||||
|
||||
if (parent)
|
||||
{
|
||||
return (LLSpatialGroup*) parent->getListener(0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return (LLSpatialGroup*)LLviewerOctreeGroup::getParent();
|
||||
}
|
||||
|
||||
BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
|
||||
|
|
@ -735,10 +542,10 @@ void LLSpatialGroup::shift(const LLVector4a &offset)
|
|||
mObjectExtents[0].add(offset);
|
||||
mObjectExtents[1].add(offset);
|
||||
|
||||
if (!mSpatialPartition->mRenderByGroup &&
|
||||
mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TREE &&
|
||||
mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TERRAIN &&
|
||||
mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_BRIDGE)
|
||||
if (!getSpatialPartition()->mRenderByGroup &&
|
||||
getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE &&
|
||||
getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN &&
|
||||
getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE)
|
||||
{
|
||||
setState(GEOM_DIRTY);
|
||||
gPipeline.markRebuild(this, TRUE);
|
||||
|
|
@ -839,135 +646,15 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
|
|||
}
|
||||
}
|
||||
|
||||
//=====================================
|
||||
// Occlusion State Set/Clear
|
||||
//=====================================
|
||||
class LLSpatialSetOcclusionState : public OctreeTraveler
|
||||
{
|
||||
public:
|
||||
U32 mState;
|
||||
LLSpatialSetOcclusionState(U32 state) : mState(state) { }
|
||||
virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); }
|
||||
};
|
||||
|
||||
class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState
|
||||
{
|
||||
public:
|
||||
LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { }
|
||||
|
||||
virtual void traverse(const OctreeNode* n)
|
||||
{
|
||||
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
|
||||
|
||||
if (!group->isOcclusionState(mState))
|
||||
{
|
||||
OctreeTraveler::traverse(n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void LLSpatialGroup::setOcclusionState(U32 state, S32 mode)
|
||||
{
|
||||
if (mode > STATE_MODE_SINGLE)
|
||||
{
|
||||
if (mode == STATE_MODE_DIFF)
|
||||
{
|
||||
LLSpatialSetOcclusionStateDiff setter(state);
|
||||
setter.traverse(mOctreeNode);
|
||||
}
|
||||
else if (mode == STATE_MODE_BRANCH)
|
||||
{
|
||||
LLSpatialSetOcclusionState setter(state);
|
||||
setter.traverse(mOctreeNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
mOcclusionState[i] |= state;
|
||||
|
||||
if ((state & DISCARD_QUERY) && mOcclusionQuery[i])
|
||||
{
|
||||
release_occlusion_query_object_name(mOcclusionQuery[i]);
|
||||
mOcclusionQuery[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
|
||||
if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
release_occlusion_query_object_name(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LLSpatialClearOcclusionState : public OctreeTraveler
|
||||
{
|
||||
public:
|
||||
U32 mState;
|
||||
|
||||
LLSpatialClearOcclusionState(U32 state) : mState(state) { }
|
||||
virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); }
|
||||
};
|
||||
|
||||
class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState
|
||||
{
|
||||
public:
|
||||
LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { }
|
||||
|
||||
virtual void traverse(const OctreeNode* n)
|
||||
{
|
||||
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
|
||||
|
||||
if (group->isOcclusionState(mState))
|
||||
{
|
||||
OctreeTraveler::traverse(n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
|
||||
{
|
||||
if (mode > STATE_MODE_SINGLE)
|
||||
{
|
||||
if (mode == STATE_MODE_DIFF)
|
||||
{
|
||||
LLSpatialClearOcclusionStateDiff clearer(state);
|
||||
clearer.traverse(mOctreeNode);
|
||||
}
|
||||
else if (mode == STATE_MODE_BRANCH)
|
||||
{
|
||||
LLSpatialClearOcclusionState clearer(state);
|
||||
clearer.traverse(mOctreeNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
mOcclusionState[i] &= ~state;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
|
||||
}
|
||||
}
|
||||
//======================================
|
||||
// Octree Listener Implementation
|
||||
//======================================
|
||||
|
||||
LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLviewerOctreeGroup(node),
|
||||
LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLOcclusionCullingGroup(node, part),
|
||||
mObjectBoxSize(1.f),
|
||||
mGeometryBytes(0),
|
||||
mSurfaceArea(0.f),
|
||||
mBuilt(0.f),
|
||||
mSpatialPartition(part),
|
||||
mBuilt(0.f),
|
||||
mVertexBuffer(NULL),
|
||||
mBufferUsage(part->mBufferUsage),
|
||||
mDistance(0.f),
|
||||
|
|
@ -990,21 +677,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLv
|
|||
setState(SG_INITIAL_STATE_MASK);
|
||||
gPipeline.markRebuild(this, TRUE);
|
||||
|
||||
part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
|
||||
mLODHash = part->mLODSeed;
|
||||
|
||||
OctreeNode* oct_parent = node->getOctParent();
|
||||
|
||||
LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL;
|
||||
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
mOcclusionQuery[i] = 0;
|
||||
mOcclusionIssued[i] = 0;
|
||||
mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
|
||||
mVisible[i] = 0;
|
||||
}
|
||||
|
||||
mRadius = 1;
|
||||
mPixelArea = 1024.f;
|
||||
}
|
||||
|
|
@ -1030,10 +702,10 @@ void LLSpatialGroup::updateDistance(LLCamera &camera)
|
|||
#endif
|
||||
if (!isEmpty())
|
||||
{
|
||||
mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() :
|
||||
mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() :
|
||||
(F32) mOctreeNode->getSize().getLength3().getF32();
|
||||
mDistance = mSpatialPartition->calcDistance(this, camera);
|
||||
mPixelArea = mSpatialPartition->calcPixelArea(this, camera);
|
||||
mDistance = getSpatialPartition()->calcDistance(this, camera);
|
||||
mPixelArea = getSpatialPartition()->calcPixelArea(this, camera);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1056,7 +728,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
|
|||
|
||||
if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY))
|
||||
{
|
||||
if (!group->mSpatialPartition->isBridge())
|
||||
if (!group->getSpatialPartition()->isBridge())
|
||||
{
|
||||
LLVector4a view_angle = eye;
|
||||
|
||||
|
|
@ -1124,11 +796,6 @@ F32 LLSpatialGroup::getUpdateUrgency() const
|
|||
}
|
||||
}
|
||||
|
||||
BOOL LLSpatialGroup::needsUpdate()
|
||||
{
|
||||
return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL LLSpatialGroup::changeLOD()
|
||||
{
|
||||
if (hasState(ALPHA_DIRTY | OBJECT_DIRTY))
|
||||
|
|
@ -1136,11 +803,11 @@ BOOL LLSpatialGroup::changeLOD()
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if (mSpatialPartition->mSlopRatio > 0.f)
|
||||
if (getSpatialPartition()->mSlopRatio > 0.f)
|
||||
{
|
||||
F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius));
|
||||
|
||||
if (fabsf(ratio) >= mSpatialPartition->mSlopRatio)
|
||||
if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1193,7 +860,7 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)
|
|||
}
|
||||
|
||||
//clean up avatar attachment stats
|
||||
LLSpatialBridge* bridge = mSpatialPartition->asBridge();
|
||||
LLSpatialBridge* bridge = getSpatialPartition()->asBridge();
|
||||
if (bridge)
|
||||
{
|
||||
if (bridge->mAvatar.notNull())
|
||||
|
|
@ -1214,7 +881,7 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
|
|||
{
|
||||
if (child->getListenerCount() == 0)
|
||||
{
|
||||
new LLSpatialGroup(child, mSpatialPartition);
|
||||
new LLSpatialGroup(child, getSpatialPartition());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1243,14 +910,7 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion)
|
|||
|
||||
if (!keep_occlusion)
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
if (mOcclusionQuery[i])
|
||||
{
|
||||
release_occlusion_query_object_name(mOcclusionQuery[i]);
|
||||
mOcclusionQuery[i] = 0;
|
||||
}
|
||||
}
|
||||
releaseOcclusionQueryObjectNames();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1272,233 +932,13 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion)
|
|||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait");
|
||||
|
||||
void LLSpatialGroup::checkOcclusion()
|
||||
{
|
||||
if (LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_READBACK);
|
||||
LLSpatialGroup* parent = getParent();
|
||||
if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
|
||||
{ //if the parent has been marked as occluded, the child is implicitly occluded
|
||||
clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
|
||||
}
|
||||
else if (isOcclusionState(QUERY_PENDING))
|
||||
{ //otherwise, if a query is pending, read it back
|
||||
|
||||
GLuint available = 0;
|
||||
if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
|
||||
|
||||
static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion");
|
||||
|
||||
if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)
|
||||
{ //query was issued last frame, wait until it's available
|
||||
S32 max_loop = 1024;
|
||||
LLFastTimer t(FTM_OCCLUSION_WAIT);
|
||||
while (!available && max_loop-- > 0)
|
||||
{
|
||||
F32 max_time = llmin(gFrameIntervalSeconds.value()*10.f, 1.f);
|
||||
//do some usefu work while we wait
|
||||
LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
|
||||
LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
|
||||
LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
|
||||
|
||||
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
available = 1;
|
||||
}
|
||||
|
||||
if (available)
|
||||
{ //result is available, read it back, otherwise wait until next frame
|
||||
GLuint res = 1;
|
||||
if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
|
||||
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
|
||||
sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
#endif
|
||||
}
|
||||
else if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{ //delete the query to avoid holding onto hundreds of pending queries
|
||||
release_occlusion_query_object_name(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
|
||||
}
|
||||
|
||||
if (isOcclusionState(DISCARD_QUERY))
|
||||
{
|
||||
res = 2;
|
||||
}
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
assert_states_valid(this);
|
||||
clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
|
||||
assert_states_valid(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_states_valid(this);
|
||||
|
||||
setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
|
||||
|
||||
assert_states_valid(this);
|
||||
}
|
||||
|
||||
clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
|
||||
}
|
||||
}
|
||||
else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED))
|
||||
{ //check occlusion has been issued for occluded node that has not had a query issued
|
||||
assert_states_valid(this);
|
||||
clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
|
||||
assert_states_valid(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PUSH_OCCLUSION_VERTS("Push Occlusion");
|
||||
static LLFastTimer::DeclareTimer FTM_SET_OCCLUSION_STATE("Occlusion State");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_ALLOCATE("Allocate");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_BUILD("Build");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_BEGIN_QUERY("Begin Query");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_END_QUERY("End Query");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_SET_BUFFER("Set Buffer");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW_WATER("Draw Water");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW("Draw");
|
||||
|
||||
|
||||
|
||||
void LLSpatialGroup::doOcclusion(LLCamera* camera)
|
||||
{
|
||||
if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
// Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
|
||||
if (earlyFail(camera, this))
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL);
|
||||
setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
|
||||
assert_states_valid(this);
|
||||
clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
|
||||
assert_states_valid(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY))
|
||||
{
|
||||
{ //no query pending, or previous query to be discarded
|
||||
LLFastTimer t(FTM_RENDER_OCCLUSION);
|
||||
|
||||
if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_ALLOCATE);
|
||||
mOcclusionQuery[LLViewerCamera::sCurCameraID] = get_new_occlusion_query_object_name();
|
||||
}
|
||||
|
||||
// Depth clamp all water to avoid it being culled as a result of being
|
||||
// behind the far clip plane, and in the case of edge water to avoid
|
||||
// it being culled while still visible.
|
||||
bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
|
||||
(mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
|
||||
mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
|
||||
|
||||
LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
|
||||
|
||||
#if !LL_DARWIN
|
||||
U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB;
|
||||
#else
|
||||
U32 mode = GL_SAMPLES_PASSED_ARB;
|
||||
#endif
|
||||
|
||||
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
|
||||
sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
#endif
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS);
|
||||
|
||||
//store which frame this query was issued on
|
||||
mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount;
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY);
|
||||
glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
}
|
||||
|
||||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
llassert(shader);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr());
|
||||
shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE,
|
||||
mBounds[1][1]+SG_OCCLUSION_FUDGE,
|
||||
mBounds[1][2]+SG_OCCLUSION_FUDGE);
|
||||
|
||||
if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER)
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_DRAW_WATER);
|
||||
|
||||
LLGLSquashToFarClip squash(glh_get_current_projection(), 1);
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
{ //origin is invalid, draw entire box
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_DRAW);
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
{ //origin is invalid, draw entire box
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_END_QUERY);
|
||||
glEndQueryARB(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_SET_OCCLUSION_STATE);
|
||||
setOcclusionState(LLSpatialGroup::QUERY_PENDING);
|
||||
clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================
|
||||
|
||||
LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp)
|
||||
: mRenderByGroup(render_by_group), mBridge(NULL)
|
||||
{
|
||||
mRegionp = regionp;
|
||||
mOcclusionEnabled = TRUE;
|
||||
mDrawableType = 0;
|
||||
mPartitionType = LLViewerRegion::PARTITION_NONE;
|
||||
mLODSeed = 0;
|
||||
mLODPeriod = 1;
|
||||
mRegionp = regionp;
|
||||
mPartitionType = LLViewerRegion::PARTITION_NONE;
|
||||
mVertexDataMask = data_mask;
|
||||
mBufferUsage = buffer_usage;
|
||||
mDepthMask = FALSE;
|
||||
|
|
@ -1566,11 +1006,11 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL
|
|||
|
||||
BOOL was_visible = curp ? curp->isVisible() : FALSE;
|
||||
|
||||
if (curp && curp->mSpatialPartition != this)
|
||||
if (curp && curp->getSpatialPartition() != this)
|
||||
{
|
||||
//keep drawable from being garbage collected
|
||||
LLPointer<LLDrawable> ptr = drawablep;
|
||||
if (curp->mSpatialPartition->remove(drawablep, curp))
|
||||
if (curp->getSpatialPartition()->remove(drawablep, curp))
|
||||
{
|
||||
put(drawablep, was_visible);
|
||||
return;
|
||||
|
|
@ -1961,7 +1401,7 @@ public:
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup)
|
||||
if (drawable->getVObj().notNull() && !group->getSpatialPartition()->mRenderByGroup)
|
||||
{
|
||||
gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE);
|
||||
}
|
||||
|
|
@ -1985,11 +1425,6 @@ void LLSpatialPartition::resetVertexBuffers()
|
|||
dirty.traverse(mOctree);
|
||||
}
|
||||
|
||||
BOOL LLSpatialPartition::isOcclusionEnabled()
|
||||
{
|
||||
return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2;
|
||||
}
|
||||
|
||||
BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax)
|
||||
{
|
||||
LLVector4a visMina, visMaxa;
|
||||
|
|
@ -2075,51 +1510,6 @@ S32 LLSpatialPartition::cull(LLCamera &camera)
|
|||
return 0;
|
||||
}
|
||||
|
||||
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
|
||||
{
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const F32 vel = SG_OCCLUSION_FUDGE*2.f;
|
||||
LLVector4a fudge;
|
||||
fudge.splat(vel);
|
||||
|
||||
const LLVector4a* bounds = group->getBounds();
|
||||
const LLVector4a& c = bounds[0];
|
||||
LLVector4a r;
|
||||
r.setAdd(bounds[1], fudge);
|
||||
|
||||
/*if (r.magVecSquared() > 1024.0*1024.0)
|
||||
{
|
||||
return TRUE;
|
||||
}*/
|
||||
|
||||
LLVector4a e;
|
||||
e.load3(camera->getOrigin().mV);
|
||||
|
||||
LLVector4a min;
|
||||
min.setSub(c,r);
|
||||
LLVector4a max;
|
||||
max.setAdd(c,r);
|
||||
|
||||
S32 lt = e.lessThan(min).getGatheredBits() & 0x7;
|
||||
if (lt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
S32 gt = e.greaterThan(max).getGatheredBits() & 0x7;
|
||||
if (gt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void pushVerts(LLDrawInfo* params, U32 mask)
|
||||
{
|
||||
LLRenderPass::applyModelMatrix(*params);
|
||||
|
|
@ -2191,7 +1581,7 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
|
|||
|
||||
void pushBufferVerts(LLSpatialGroup* group, U32 mask)
|
||||
{
|
||||
if (group->mSpatialPartition->mRenderByGroup)
|
||||
if (group->getSpatialPartition()->mRenderByGroup)
|
||||
{
|
||||
if (!group->mDrawMap.empty())
|
||||
{
|
||||
|
|
@ -2292,7 +1682,7 @@ void renderOctree(LLSpatialGroup* group)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (!group->mSpatialPartition->isBridge())
|
||||
if (!group->getSpatialPartition()->isBridge())
|
||||
{
|
||||
gGL.pushMatrix();
|
||||
LLVector3 trans = drawable->getRegion()->getOriginAgent();
|
||||
|
|
@ -2324,7 +1714,7 @@ void renderOctree(LLSpatialGroup* group)
|
|||
}
|
||||
}
|
||||
|
||||
if (!group->mSpatialPartition->isBridge())
|
||||
if (!group->getSpatialPartition()->isBridge())
|
||||
{
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
|
@ -2336,7 +1726,7 @@ void renderOctree(LLSpatialGroup* group)
|
|||
else
|
||||
{
|
||||
if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty()
|
||||
&& group->mSpatialPartition->mRenderByGroup)
|
||||
&& group->getSpatialPartition()->mRenderByGroup)
|
||||
{
|
||||
col.setVec(0.8f, 0.4f, 0.1f, 0.1f);
|
||||
}
|
||||
|
|
@ -2373,7 +1763,7 @@ void renderOctree(LLSpatialGroup* group)
|
|||
drawBoxOutline(bounds[0], bounds[1]);
|
||||
|
||||
//draw bounding box for draw info
|
||||
/*if (group->mSpatialPartition->mRenderByGroup)
|
||||
/*if (group->getSpatialPartition()->mRenderByGroup)
|
||||
{
|
||||
gGL.diffuseColor4f(1.0f, 0.75f, 0.25f, 0.6f);
|
||||
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
|
||||
|
|
@ -3147,7 +2537,7 @@ void renderPhysicsShapes(LLSpatialGroup* group)
|
|||
LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE )
|
||||
{
|
||||
if (!group->mSpatialPartition->isBridge())
|
||||
if (!group->getSpatialPartition()->isBridge())
|
||||
{
|
||||
gGL.pushMatrix();
|
||||
LLVector3 trans = drawable->getRegion()->getOriginAgent();
|
||||
|
|
@ -4225,9 +3615,9 @@ public:
|
|||
LLVector3 local_start = mStart;
|
||||
LLVector3 local_end = mEnd;
|
||||
|
||||
if (group->mSpatialPartition->isBridge())
|
||||
if (group->getSpatialPartition()->isBridge())
|
||||
{
|
||||
LLMatrix4 local_matrix = group->mSpatialPartition->asBridge()->mDrawable->getRenderMatrix();
|
||||
LLMatrix4 local_matrix = group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix();
|
||||
local_matrix.invert();
|
||||
|
||||
local_start = mStart * local_matrix;
|
||||
|
|
|
|||
|
|
@ -55,12 +55,6 @@ class LLViewerRegion;
|
|||
|
||||
void pushVerts(LLFace* face, U32 mask);
|
||||
|
||||
// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera
|
||||
U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center);
|
||||
U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center);
|
||||
GLuint get_new_occlusion_query_object_name();
|
||||
void release_occlusion_query_object_name(GLuint name);
|
||||
|
||||
class LLDrawInfo : public LLRefCount
|
||||
{
|
||||
protected:
|
||||
|
|
@ -191,13 +185,13 @@ public:
|
|||
};
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLSpatialGroup : public LLviewerOctreeGroup
|
||||
class LLSpatialGroup : public LLOcclusionCullingGroup
|
||||
{
|
||||
friend class LLSpatialPartition;
|
||||
friend class LLOctreeStateCheck;
|
||||
public:
|
||||
|
||||
LLSpatialGroup(const LLSpatialGroup& rhs) : LLviewerOctreeGroup(rhs)
|
||||
LLSpatialGroup(const LLSpatialGroup& rhs) : LLOcclusionCullingGroup(rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
|
|
@ -218,7 +212,6 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
static std::set<GLuint> sPendingQueries; //pending occlusion queries
|
||||
static U32 sNodeCount;
|
||||
static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE
|
||||
|
||||
|
|
@ -256,17 +249,7 @@ public:
|
|||
|
||||
typedef enum
|
||||
{
|
||||
OCCLUDED = 0x00010000,
|
||||
QUERY_PENDING = 0x00020000,
|
||||
ACTIVE_OCCLUSION = 0x00040000,
|
||||
DISCARD_QUERY = 0x00080000,
|
||||
EARLY_FAIL = 0x00100000,
|
||||
} eOcclusionState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DEAD = LLviewerOctreeGroup::INVALID_STATE,
|
||||
GEOM_DIRTY = (DEAD << 1),
|
||||
GEOM_DIRTY = LLviewerOctreeGroup::INVALID_STATE,
|
||||
ALPHA_DIRTY = (GEOM_DIRTY << 1),
|
||||
IN_IMAGE_QUEUE = (ALPHA_DIRTY << 1),
|
||||
IMAGE_DIRTY = (IN_IMAGE_QUEUE << 1),
|
||||
|
|
@ -275,33 +258,19 @@ public:
|
|||
IN_BUILD_Q1 = (NEW_DRAWINFO << 1),
|
||||
IN_BUILD_Q2 = (IN_BUILD_Q1 << 1),
|
||||
STATE_MASK = 0x0000FFFF,
|
||||
} eSpatialState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_MODE_SINGLE = 0, //set one node
|
||||
STATE_MODE_BRANCH, //set entire branch
|
||||
STATE_MODE_DIFF, //set entire branch as long as current state is different
|
||||
STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras
|
||||
} eSetStateMode;
|
||||
} eSpatialState;
|
||||
|
||||
LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
|
||||
|
||||
BOOL isHUDGroup() ;
|
||||
BOOL isDead() { return hasState(DEAD); }
|
||||
BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
|
||||
BOOL isHUDGroup() ;
|
||||
|
||||
void clearDrawMap();
|
||||
void validate();
|
||||
void checkStates();
|
||||
void validateDrawMap();
|
||||
|
||||
void setState(U32 state, S32 mode);
|
||||
void clearState(U32 state, S32 mode);
|
||||
void clearState(U32 state) {mState &= ~state;}
|
||||
|
||||
void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
|
||||
void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
|
||||
void clearState(U32 state) {mState &= ~state;}
|
||||
|
||||
LLSpatialGroup* getParent();
|
||||
|
||||
|
|
@ -309,13 +278,10 @@ public:
|
|||
BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE);
|
||||
BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group
|
||||
BOOL isRecentlyVisible() const;
|
||||
void shift(const LLVector4a &offset);
|
||||
void checkOcclusion(); //read back last occlusion query (if any)
|
||||
void doOcclusion(LLCamera* camera); //issue occlusion query
|
||||
void shift(const LLVector4a &offset);
|
||||
void destroyGL(bool keep_occlusion = false);
|
||||
|
||||
void updateDistance(LLCamera& camera);
|
||||
BOOL needsUpdate();
|
||||
F32 getUpdateUrgency() const;
|
||||
BOOL changeLOD();
|
||||
void rebuildGeom();
|
||||
|
|
@ -327,6 +293,8 @@ public:
|
|||
|
||||
void drawObjectBox(LLColor4 col);
|
||||
|
||||
LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;}
|
||||
|
||||
//LISTENER FUNCTIONS
|
||||
virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face);
|
||||
virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face);
|
||||
|
|
@ -372,12 +340,8 @@ private:
|
|||
//-------------------
|
||||
|
||||
protected:
|
||||
virtual ~LLSpatialGroup();
|
||||
|
||||
U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
|
||||
U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS];
|
||||
|
||||
S32 mLODHash;
|
||||
virtual ~LLSpatialGroup();
|
||||
|
||||
static S32 sLODSeed;
|
||||
|
||||
public:
|
||||
|
|
@ -387,11 +351,9 @@ public:
|
|||
U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node
|
||||
F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node
|
||||
|
||||
F32 mBuilt;
|
||||
LLSpatialPartition* mSpatialPartition;
|
||||
F32 mBuilt;
|
||||
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
|
||||
U32 mBufferUsage;
|
||||
draw_map_t mDrawMap;
|
||||
|
|
@ -461,21 +423,18 @@ public:
|
|||
void renderDebug();
|
||||
void renderIntersectingBBoxes(LLCamera* camera);
|
||||
void restoreGL();
|
||||
void resetVertexBuffers();
|
||||
BOOL isOcclusionEnabled();
|
||||
void resetVertexBuffers();
|
||||
|
||||
BOOL getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax);
|
||||
|
||||
public:
|
||||
LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this
|
||||
// use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe
|
||||
// to call asBridge() from the destructor
|
||||
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
|
||||
// to call asBridge() from the destructor
|
||||
|
||||
BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
|
||||
U32 mBufferUsage;
|
||||
U32 mDrawableType;
|
||||
const BOOL mRenderByGroup;
|
||||
U32 mLODSeed;
|
||||
U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed)
|
||||
U32 mBufferUsage;
|
||||
const BOOL mRenderByGroup;
|
||||
U32 mVertexDataMask;
|
||||
F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25);
|
||||
BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llvieweroctree.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llviewershadermgr.h"
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//static variables definitions
|
||||
|
|
@ -37,6 +42,100 @@ BOOL LLViewerOctreeDebug::sInDebug = FALSE;
|
|||
//-----------------------------------------------------------------------------------
|
||||
//some global functions definitions
|
||||
//-----------------------------------------------------------------------------------
|
||||
typedef enum
|
||||
{
|
||||
b000 = 0x00,
|
||||
b001 = 0x01,
|
||||
b010 = 0x02,
|
||||
b011 = 0x03,
|
||||
b100 = 0x04,
|
||||
b101 = 0x05,
|
||||
b110 = 0x06,
|
||||
b111 = 0x07,
|
||||
} eLoveTheBits;
|
||||
|
||||
//contact Runitai Linden for a copy of the SL object used to write this table
|
||||
//basically, you give the table a bitmask of the look-at vector to a node and it
|
||||
//gives you a triangle fan index array
|
||||
static U16 sOcclusionIndices[] =
|
||||
{
|
||||
//000
|
||||
b111, b110, b010, b011, b001, b101, b100, b110,
|
||||
//001
|
||||
b011, b010, b000, b001, b101, b111, b110, b010,
|
||||
//010
|
||||
b101, b100, b110, b111, b011, b001, b000, b100,
|
||||
//011
|
||||
b001, b000, b100, b101, b111, b011, b010, b000,
|
||||
//100
|
||||
b110, b000, b010, b011, b111, b101, b100, b000,
|
||||
//101
|
||||
b010, b100, b000, b001, b011, b111, b110, b100,
|
||||
//110
|
||||
b100, b010, b110, b111, b101, b001, b000, b010,
|
||||
//111
|
||||
b000, b110, b100, b101, b001, b011, b010, b110,
|
||||
};
|
||||
|
||||
U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center)
|
||||
{
|
||||
LLVector4a origin;
|
||||
origin.load3(camera->getOrigin().mV);
|
||||
|
||||
S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7;
|
||||
|
||||
return cypher*8;
|
||||
}
|
||||
|
||||
U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center)
|
||||
{
|
||||
LLVector4a origin;
|
||||
origin.load3(camera->getOrigin().mV);
|
||||
|
||||
S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7;
|
||||
|
||||
return (U8*) (sOcclusionIndices+cypher*8);
|
||||
}
|
||||
|
||||
//create a vertex buffer for efficiently rendering cubes
|
||||
LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage)
|
||||
{
|
||||
LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage);
|
||||
|
||||
ret->allocateBuffer(8, 64, true);
|
||||
|
||||
LLStrider<LLVector3> pos;
|
||||
LLStrider<U16> idx;
|
||||
|
||||
ret->getVertexStrider(pos);
|
||||
ret->getIndexStrider(idx);
|
||||
|
||||
pos[0] = LLVector3(-1,-1,-1);
|
||||
pos[1] = LLVector3(-1,-1, 1);
|
||||
pos[2] = LLVector3(-1, 1,-1);
|
||||
pos[3] = LLVector3(-1, 1, 1);
|
||||
pos[4] = LLVector3( 1,-1,-1);
|
||||
pos[5] = LLVector3( 1,-1, 1);
|
||||
pos[6] = LLVector3( 1, 1,-1);
|
||||
pos[7] = LLVector3( 1, 1, 1);
|
||||
|
||||
for (U32 i = 0; i < 64; i++)
|
||||
{
|
||||
idx[i] = sOcclusionIndices[i];
|
||||
}
|
||||
|
||||
ret->flush();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define LL_TRACK_PENDING_OCCLUSION_QUERIES 0
|
||||
|
||||
const F32 SG_OCCLUSION_FUDGE = 0.25f;
|
||||
#define SG_DISCARD_TOLERANCE 0.01f
|
||||
|
||||
|
||||
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad)
|
||||
{
|
||||
return AABBSphereIntersectR2(min, max, origin, rad*rad);
|
||||
|
|
@ -537,6 +636,11 @@ void LLviewerOctreeGroup::handleChildRemoval(const OctreeNode* parent, const Oct
|
|||
|
||||
LLviewerOctreeGroup* LLviewerOctreeGroup::getParent()
|
||||
{
|
||||
if (isDead())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!mOctreeNode)
|
||||
{
|
||||
return NULL;
|
||||
|
|
@ -626,10 +730,519 @@ void LLviewerOctreeGroup::setVisible()
|
|||
{
|
||||
mVisible[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame();
|
||||
}
|
||||
|
||||
void LLviewerOctreeGroup::checkStates()
|
||||
{
|
||||
#if LL_OCTREE_PARANOIA_CHECK
|
||||
//LLOctreeStateCheck checker;
|
||||
//checker.traverse(mOctreeNode);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
//occulsion culling functions and classes
|
||||
//-------------------------------------------------------------------------------------------
|
||||
std::set<U32> LLOcclusionCullingGroup::sPendingQueries;
|
||||
class LLOcclusionQueryPool : public LLGLNamePool
|
||||
{
|
||||
public:
|
||||
LLOcclusionQueryPool()
|
||||
{
|
||||
mCurQuery = 1;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::list<GLuint> mAvailableName;
|
||||
GLuint mCurQuery;
|
||||
|
||||
virtual GLuint allocateName()
|
||||
{
|
||||
GLuint ret = 0;
|
||||
|
||||
if (!mAvailableName.empty())
|
||||
{
|
||||
ret = mAvailableName.front();
|
||||
mAvailableName.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = mCurQuery++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual void releaseName(GLuint name)
|
||||
{
|
||||
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
|
||||
LLSpatialGroup::sPendingQueries.erase(name);
|
||||
#endif
|
||||
llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end());
|
||||
mAvailableName.push_back(name);
|
||||
}
|
||||
};
|
||||
|
||||
static LLOcclusionQueryPool sQueryPool;
|
||||
U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName()
|
||||
{
|
||||
return sQueryPool.allocate();
|
||||
}
|
||||
|
||||
void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(GLuint name)
|
||||
{
|
||||
sQueryPool.release(name);
|
||||
}
|
||||
|
||||
//=====================================
|
||||
// Occlusion State Set/Clear
|
||||
//=====================================
|
||||
class LLSpatialSetOcclusionState : public OctreeTraveler
|
||||
{
|
||||
public:
|
||||
U32 mState;
|
||||
LLSpatialSetOcclusionState(U32 state) : mState(state) { }
|
||||
virtual void visit(const OctreeNode* branch) { ((LLOcclusionCullingGroup*) branch->getListener(0))->setOcclusionState(mState); }
|
||||
};
|
||||
|
||||
class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState
|
||||
{
|
||||
public:
|
||||
LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { }
|
||||
|
||||
virtual void traverse(const OctreeNode* n)
|
||||
{
|
||||
LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*) n->getListener(0);
|
||||
|
||||
if (!group->isOcclusionState(mState))
|
||||
{
|
||||
OctreeTraveler::traverse(n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part) :
|
||||
LLviewerOctreeGroup(node),
|
||||
mSpatialPartition(part)
|
||||
{
|
||||
part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
|
||||
mLODHash = part->mLODSeed;
|
||||
|
||||
OctreeNode* oct_parent = node->getOctParent();
|
||||
LLOcclusionCullingGroup* parent = oct_parent ? (LLOcclusionCullingGroup*) oct_parent->getListener(0) : NULL;
|
||||
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
mOcclusionQuery[i] = 0;
|
||||
mOcclusionIssued[i] = 0;
|
||||
mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
|
||||
mVisible[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LLOcclusionCullingGroup::~LLOcclusionCullingGroup()
|
||||
{
|
||||
releaseOcclusionQueryObjectNames();
|
||||
}
|
||||
|
||||
BOOL LLOcclusionCullingGroup::needsUpdate()
|
||||
{
|
||||
return (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child)
|
||||
{
|
||||
if (child->getListenerCount() == 0)
|
||||
{
|
||||
new LLOcclusionCullingGroup(child, mSpatialPartition);
|
||||
}
|
||||
else
|
||||
{
|
||||
OCT_ERRS << "LLOcclusionCullingGroup redundancy detected." << llendl;
|
||||
}
|
||||
|
||||
unbound();
|
||||
|
||||
((LLviewerOctreeGroup*)child->getListener(0))->unbound();
|
||||
}
|
||||
|
||||
void LLOcclusionCullingGroup::releaseOcclusionQueryObjectNames()
|
||||
{
|
||||
if (gGLManager.mHasOcclusionQuery)
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
|
||||
{
|
||||
if (mOcclusionQuery[i])
|
||||
{
|
||||
releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
|
||||
mOcclusionQuery[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode)
|
||||
{
|
||||
if (mode > STATE_MODE_SINGLE)
|
||||
{
|
||||
if (mode == STATE_MODE_DIFF)
|
||||
{
|
||||
LLSpatialSetOcclusionStateDiff setter(state);
|
||||
setter.traverse(mOctreeNode);
|
||||
}
|
||||
else if (mode == STATE_MODE_BRANCH)
|
||||
{
|
||||
LLSpatialSetOcclusionState setter(state);
|
||||
setter.traverse(mOctreeNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
mOcclusionState[i] |= state;
|
||||
|
||||
if ((state & DISCARD_QUERY) && mOcclusionQuery[i])
|
||||
{
|
||||
releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
|
||||
mOcclusionQuery[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
|
||||
if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LLSpatialClearOcclusionState : public OctreeTraveler
|
||||
{
|
||||
public:
|
||||
U32 mState;
|
||||
|
||||
LLSpatialClearOcclusionState(U32 state) : mState(state) { }
|
||||
virtual void visit(const OctreeNode* branch) { ((LLOcclusionCullingGroup*) branch->getListener(0))->clearOcclusionState(mState); }
|
||||
};
|
||||
|
||||
class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState
|
||||
{
|
||||
public:
|
||||
LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { }
|
||||
|
||||
virtual void traverse(const OctreeNode* n)
|
||||
{
|
||||
LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*) n->getListener(0);
|
||||
|
||||
if (group->isOcclusionState(mState))
|
||||
{
|
||||
OctreeTraveler::traverse(n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode)
|
||||
{
|
||||
if (mode > STATE_MODE_SINGLE)
|
||||
{
|
||||
if (mode == STATE_MODE_DIFF)
|
||||
{
|
||||
LLSpatialClearOcclusionStateDiff clearer(state);
|
||||
clearer.traverse(mOctreeNode);
|
||||
}
|
||||
else if (mode == STATE_MODE_BRANCH)
|
||||
{
|
||||
LLSpatialClearOcclusionState clearer(state);
|
||||
clearer.traverse(mOctreeNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
|
||||
{
|
||||
mOcclusionState[i] &= ~state;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
|
||||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait");
|
||||
|
||||
BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera)
|
||||
{
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const F32 vel = SG_OCCLUSION_FUDGE*2.f;
|
||||
LLVector4a fudge;
|
||||
fudge.splat(vel);
|
||||
|
||||
const LLVector4a* bounds = getBounds();
|
||||
const LLVector4a& c = bounds[0];
|
||||
LLVector4a r;
|
||||
r.setAdd(bounds[1], fudge);
|
||||
|
||||
/*if (r.magVecSquared() > 1024.0*1024.0)
|
||||
{
|
||||
return TRUE;
|
||||
}*/
|
||||
|
||||
LLVector4a e;
|
||||
e.load3(camera->getOrigin().mV);
|
||||
|
||||
LLVector4a min;
|
||||
min.setSub(c,r);
|
||||
LLVector4a max;
|
||||
max.setAdd(c,r);
|
||||
|
||||
S32 lt = e.lessThan(min).getGatheredBits() & 0x7;
|
||||
if (lt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
S32 gt = e.greaterThan(max).getGatheredBits() & 0x7;
|
||||
if (gt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLOcclusionCullingGroup::checkOcclusion()
|
||||
{
|
||||
if (LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_READBACK);
|
||||
LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent();
|
||||
if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
|
||||
{ //if the parent has been marked as occluded, the child is implicitly occluded
|
||||
clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
|
||||
}
|
||||
else if (isOcclusionState(QUERY_PENDING))
|
||||
{ //otherwise, if a query is pending, read it back
|
||||
|
||||
GLuint available = 0;
|
||||
if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
|
||||
|
||||
static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion");
|
||||
|
||||
if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)
|
||||
{ //query was issued last frame, wait until it's available
|
||||
S32 max_loop = 1024;
|
||||
LLFastTimer t(FTM_OCCLUSION_WAIT);
|
||||
while (!available && max_loop-- > 0)
|
||||
{
|
||||
//do some usefu work while we wait
|
||||
F32 max_time = llmin(gFrameIntervalSeconds.value()*10.f, 1.f);
|
||||
LLAppViewer::instance()->updateTextureThreads(max_time);
|
||||
|
||||
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
available = 1;
|
||||
}
|
||||
|
||||
if (available)
|
||||
{ //result is available, read it back, otherwise wait until next frame
|
||||
GLuint res = 1;
|
||||
if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
|
||||
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
|
||||
sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
#endif
|
||||
}
|
||||
else if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{ //delete the query to avoid holding onto hundreds of pending queries
|
||||
releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
|
||||
}
|
||||
|
||||
if (isOcclusionState(DISCARD_QUERY))
|
||||
{
|
||||
res = 2;
|
||||
}
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
assert_states_valid(this);
|
||||
clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
|
||||
assert_states_valid(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_states_valid(this);
|
||||
|
||||
setOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
|
||||
|
||||
assert_states_valid(this);
|
||||
}
|
||||
|
||||
clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
|
||||
}
|
||||
}
|
||||
else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
|
||||
{ //check occlusion has been issued for occluded node that has not had a query issued
|
||||
assert_states_valid(this);
|
||||
clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
|
||||
assert_states_valid(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PUSH_OCCLUSION_VERTS("Push Occlusion");
|
||||
static LLFastTimer::DeclareTimer FTM_SET_OCCLUSION_STATE("Occlusion State");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_ALLOCATE("Allocate");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_BUILD("Build");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_BEGIN_QUERY("Begin Query");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_END_QUERY("End Query");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_SET_BUFFER("Set Buffer");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW_WATER("Draw Water");
|
||||
static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW("Draw");
|
||||
|
||||
void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera)
|
||||
{
|
||||
if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
// Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
|
||||
if (earlyFail(camera))
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL);
|
||||
setOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY);
|
||||
assert_states_valid(this);
|
||||
clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
|
||||
assert_states_valid(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY))
|
||||
{
|
||||
{ //no query pending, or previous query to be discarded
|
||||
LLFastTimer t(FTM_RENDER_OCCLUSION);
|
||||
|
||||
if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_ALLOCATE);
|
||||
mOcclusionQuery[LLViewerCamera::sCurCameraID] = getNewOcclusionQueryObjectName();
|
||||
}
|
||||
|
||||
// Depth clamp all water to avoid it being culled as a result of being
|
||||
// behind the far clip plane, and in the case of edge water to avoid
|
||||
// it being culled while still visible.
|
||||
bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
|
||||
(mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
|
||||
mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
|
||||
|
||||
LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
|
||||
|
||||
#if !LL_DARWIN
|
||||
U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB;
|
||||
#else
|
||||
U32 mode = GL_SAMPLES_PASSED_ARB;
|
||||
#endif
|
||||
|
||||
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
|
||||
sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
#endif
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS);
|
||||
|
||||
//store which frame this query was issued on
|
||||
mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount;
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY);
|
||||
glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
}
|
||||
|
||||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
llassert(shader);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr());
|
||||
shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE,
|
||||
mBounds[1][1]+SG_OCCLUSION_FUDGE,
|
||||
mBounds[1][2]+SG_OCCLUSION_FUDGE);
|
||||
|
||||
if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER)
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_DRAW_WATER);
|
||||
|
||||
LLGLSquashToFarClip squash(glh_get_current_projection(), 1);
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
{ //origin is invalid, draw entire box
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_DRAW);
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
{ //origin is invalid, draw entire box
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_OCCLUSION_END_QUERY);
|
||||
glEndQueryARB(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_SET_OCCLUSION_STATE);
|
||||
setOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING);
|
||||
clearOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------
|
||||
//end of occulsion culling functions and classes
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//class LLViewerOctreePartition definitions
|
||||
//-----------------------------------------------------------------------------------
|
||||
LLViewerOctreePartition::LLViewerOctreePartition() : mRegionp(NULL)
|
||||
LLViewerOctreePartition::LLViewerOctreePartition() :
|
||||
mRegionp(NULL),
|
||||
mOcclusionEnabled(TRUE),
|
||||
mDrawableType(0),
|
||||
mLODSeed(0),
|
||||
mLODPeriod(1)
|
||||
{
|
||||
LLVector4a center, size;
|
||||
center.splat(0.f);
|
||||
|
|
@ -644,6 +1257,11 @@ LLViewerOctreePartition::~LLViewerOctreePartition()
|
|||
mOctree = NULL;
|
||||
}
|
||||
|
||||
BOOL LLViewerOctreePartition::isOcclusionEnabled()
|
||||
{
|
||||
return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//class LLViewerOctreeCull definitions
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class LLViewerRegion;
|
|||
class LLViewerOctreeEntryData;
|
||||
class LLviewerOctreeGroup;
|
||||
class LLViewerOctreeEntry;
|
||||
class LLViewerOctreePartition;
|
||||
|
||||
typedef LLOctreeListener<LLViewerOctreeEntry> OctreeListener;
|
||||
typedef LLTreeNode<LLViewerOctreeEntry> TreeNode;
|
||||
|
|
@ -50,6 +51,18 @@ typedef LLOctreeNode<LLViewerOctreeEntry> OctreeNode;
|
|||
typedef LLOctreeRoot<LLViewerOctreeEntry> OctreeRoot;
|
||||
typedef LLOctreeTraveler<LLViewerOctreeEntry> OctreeTraveler;
|
||||
|
||||
#if LL_OCTREE_PARANOIA_CHECK
|
||||
#define assert_octree_valid(x) x->validate()
|
||||
#define assert_states_valid(x) ((LLviewerOctreeGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates()
|
||||
#else
|
||||
#define assert_octree_valid(x)
|
||||
#define assert_states_valid(x)
|
||||
#endif
|
||||
|
||||
// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera
|
||||
U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center);
|
||||
U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center);
|
||||
|
||||
S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad);
|
||||
S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &radius_squared);
|
||||
|
||||
|
|
@ -178,14 +191,15 @@ class LLviewerOctreeGroup : public LLOctreeListener<LLViewerOctreeEntry>
|
|||
protected:
|
||||
~LLviewerOctreeGroup();
|
||||
|
||||
public:
|
||||
public:
|
||||
enum
|
||||
{
|
||||
CLEAN = 0x00000000,
|
||||
DIRTY = 0x00000001,
|
||||
OBJECT_DIRTY = 0x00000002,
|
||||
SKIP_FRUSTUM_CHECK = 0x00000004,
|
||||
INVALID_STATE = 0x00000008,
|
||||
DEAD = 0x00000008,
|
||||
INVALID_STATE = 0x00000010,
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
@ -213,6 +227,8 @@ public:
|
|||
|
||||
virtual void unbound();
|
||||
virtual void rebound();
|
||||
|
||||
BOOL isDead() { return hasState(DEAD); }
|
||||
|
||||
void setVisible();
|
||||
BOOL isVisible() const;
|
||||
|
|
@ -248,9 +264,11 @@ public:
|
|||
U32 getElementCount() const { return mOctreeNode->getElementCount(); }
|
||||
bool hasElement(LLViewerOctreeEntryData* data);
|
||||
|
||||
protected:
|
||||
void checkStates();
|
||||
private:
|
||||
virtual bool boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut);
|
||||
|
||||
virtual bool boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut);
|
||||
|
||||
protected:
|
||||
U32 mState;
|
||||
OctreeNode* mOctreeNode;
|
||||
|
|
@ -258,12 +276,76 @@ protected:
|
|||
LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects)
|
||||
LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node
|
||||
LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children
|
||||
LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node
|
||||
LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node
|
||||
|
||||
public:
|
||||
S32 mVisible[LLViewerCamera::NUM_CAMERAS];
|
||||
S32 mVisible[LLViewerCamera::NUM_CAMERAS];
|
||||
|
||||
}LL_ALIGN_POSTFIX(16);
|
||||
|
||||
//octree group which has capability to support occlusion culling
|
||||
//LL_ALIGN_PREFIX(16)
|
||||
class LLOcclusionCullingGroup : public LLviewerOctreeGroup
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
OCCLUDED = 0x00010000,
|
||||
QUERY_PENDING = 0x00020000,
|
||||
ACTIVE_OCCLUSION = 0x00040000,
|
||||
DISCARD_QUERY = 0x00080000,
|
||||
EARLY_FAIL = 0x00100000,
|
||||
} eOcclusionState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_MODE_SINGLE = 0, //set one node
|
||||
STATE_MODE_BRANCH, //set entire branch
|
||||
STATE_MODE_DIFF, //set entire branch as long as current state is different
|
||||
STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras
|
||||
} eSetStateMode;
|
||||
|
||||
public:
|
||||
LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part);
|
||||
LLOcclusionCullingGroup(const LLOcclusionCullingGroup& rhs) : LLviewerOctreeGroup(rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
~LLOcclusionCullingGroup();
|
||||
|
||||
void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
|
||||
void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
|
||||
void checkOcclusion(); //read back last occlusion query (if any)
|
||||
void doOcclusion(LLCamera* camera); //issue occlusion query
|
||||
BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
|
||||
|
||||
BOOL needsUpdate();
|
||||
|
||||
//virtual
|
||||
void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
|
||||
|
||||
static U32 getNewOcclusionQueryObjectName();
|
||||
static void releaseOcclusionQueryObjectName(U32 name);
|
||||
|
||||
protected:
|
||||
void releaseOcclusionQueryObjectNames();
|
||||
|
||||
private:
|
||||
BOOL earlyFail(LLCamera* camera);
|
||||
|
||||
protected:
|
||||
U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
|
||||
U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS];
|
||||
|
||||
S32 mLODHash;
|
||||
|
||||
LLViewerOctreePartition* mSpatialPartition;
|
||||
U32 mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
|
||||
|
||||
public:
|
||||
static std::set<U32> sPendingQueries;
|
||||
};//LL_ALIGN_POSTFIX(16);
|
||||
|
||||
class LLViewerOctreePartition
|
||||
{
|
||||
public:
|
||||
|
|
@ -272,11 +354,16 @@ public:
|
|||
|
||||
// Cull on arbitrary frustum
|
||||
virtual S32 cull(LLCamera &camera) = 0;
|
||||
BOOL isOcclusionEnabled();
|
||||
|
||||
public:
|
||||
U32 mPartitionType;
|
||||
U32 mDrawableType;
|
||||
OctreeNode* mOctree;
|
||||
LLViewerRegion* mRegionp; // the region this partition belongs to.
|
||||
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
|
||||
U32 mLODSeed;
|
||||
U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed)
|
||||
};
|
||||
|
||||
class LLViewerOctreeCull : public OctreeTraveler
|
||||
|
|
|
|||
|
|
@ -595,9 +595,9 @@ public:
|
|||
|
||||
ypos += y_inc;
|
||||
|
||||
if (!LLSpatialGroup::sPendingQueries.empty())
|
||||
if (!LLOcclusionCullingGroup::sPendingQueries.empty())
|
||||
{
|
||||
addText(xpos,ypos, llformat("%d Queries pending", LLSpatialGroup::sPendingQueries.size()));
|
||||
addText(xpos,ypos, llformat("%d Queries pending", LLOcclusionCullingGroup::sPendingQueries.size()));
|
||||
ypos += y_inc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -373,10 +373,11 @@ void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scal
|
|||
//-------------------------------------------------------------------
|
||||
LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp)
|
||||
{
|
||||
mLODPeriod = 16;
|
||||
mRegionp = regionp;
|
||||
mPartitionType = LLViewerRegion::PARTITION_VO_CACHE;
|
||||
|
||||
new LLviewerOctreeGroup(mOctree);
|
||||
new LLOcclusionCullingGroup(mOctree, this);
|
||||
}
|
||||
|
||||
void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry)
|
||||
|
|
@ -401,11 +402,31 @@ public:
|
|||
mLocalShift = shift;
|
||||
}
|
||||
|
||||
virtual bool earlyFail(LLviewerOctreeGroup* base_group)
|
||||
{
|
||||
LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group;
|
||||
if(group->needsUpdate())
|
||||
{
|
||||
return false; //needs to issue new occlusion culling check.
|
||||
}
|
||||
|
||||
group->checkOcclusion();
|
||||
|
||||
if (group->getOctreeNode()->getParent() && //never occlusion cull the root node
|
||||
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
|
||||
group->isOcclusionState(LLSpatialGroup::OCCLUDED))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual S32 frustumCheck(const LLviewerOctreeGroup* group)
|
||||
{
|
||||
//S32 res = AABBInRegionFrustumGroupBounds(group);
|
||||
S32 res = AABBInRegionFrustumGroupBounds(group);
|
||||
|
||||
S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group);
|
||||
//S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group);
|
||||
if (res != 0)
|
||||
{
|
||||
res = llmin(res, AABBRegionSphereIntersectGroupExtents(group, mLocalShift));
|
||||
|
|
@ -415,9 +436,9 @@ public:
|
|||
|
||||
virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group)
|
||||
{
|
||||
//S32 res = AABBInRegionFrustumObjectBounds(group);
|
||||
S32 res = AABBInRegionFrustumObjectBounds(group);
|
||||
|
||||
S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group);
|
||||
//S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group);
|
||||
if (res != 0)
|
||||
{
|
||||
res = llmin(res, AABBRegionSphereIntersectObjectExtents(group, mLocalShift));
|
||||
|
|
@ -427,7 +448,15 @@ public:
|
|||
|
||||
virtual void processGroup(LLviewerOctreeGroup* base_group)
|
||||
{
|
||||
mRegionp->addVisibleGroup(base_group);
|
||||
LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group;
|
||||
if (group->needsUpdate() || group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
|
||||
{
|
||||
((LLOcclusionCullingGroup*)group)->doOcclusion(mCamera);
|
||||
group->setVisible();
|
||||
return; //wait for occlusion culling results
|
||||
}
|
||||
|
||||
mRegionp->addVisibleGroup(group);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -4190,7 +4190,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
|
||||
LLVOAvatar* pAvatarVO = NULL;
|
||||
|
||||
LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
|
||||
LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
|
||||
if (bridge)
|
||||
{
|
||||
if (bridge->mAvatar.isNull())
|
||||
|
|
@ -4227,10 +4227,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
std::vector<LLFace*> simple_faces;
|
||||
|
||||
std::vector<LLFace*> alpha_faces;
|
||||
U32 useage = group->mSpatialPartition->mBufferUsage;
|
||||
U32 useage = group->getSpatialPartition()->mBufferUsage;
|
||||
|
||||
U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask);
|
||||
U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask);
|
||||
U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
|
||||
U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
|
||||
max_vertices = llmin(max_vertices, (U32) 65535);
|
||||
|
||||
U32 cur_total = 0;
|
||||
|
|
@ -4837,7 +4837,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
#endif
|
||||
|
||||
//calculate maximum number of vertices to store in a single buffer
|
||||
U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask);
|
||||
U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
|
||||
max_vertices = llmin(max_vertices, (U32) 65535);
|
||||
|
||||
{
|
||||
|
|
@ -5228,7 +5228,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
|
||||
{
|
||||
//initialize to default usage for this partition
|
||||
U32 usage = group->mSpatialPartition->mBufferUsage;
|
||||
U32 usage = group->getSpatialPartition()->mBufferUsage;
|
||||
|
||||
//clear off any old faces
|
||||
mFaceList.clear();
|
||||
|
|
|
|||
|
|
@ -1663,7 +1663,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable)
|
|||
if (drawablep->getSpatialGroup())
|
||||
{
|
||||
LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION);
|
||||
if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
|
||||
if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup()))
|
||||
{
|
||||
#ifdef LL_RELEASE_FOR_DOWNLOAD
|
||||
llwarns << "Couldn't remove object from spatial group!" << llendl;
|
||||
|
|
@ -2480,7 +2480,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
|
|||
|
||||
assertInitialized();
|
||||
|
||||
if (!group->mSpatialPartition->mRenderByGroup)
|
||||
if (!group->getSpatialPartition()->mRenderByGroup)
|
||||
{ //render by drawable
|
||||
sCull->pushDrawableGroup(group);
|
||||
}
|
||||
|
|
@ -2729,7 +2729,7 @@ void LLPipeline::rebuildGroups()
|
|||
{
|
||||
group->rebuildGeom();
|
||||
|
||||
if (group->mSpatialPartition->mRenderByGroup)
|
||||
if (group->getSpatialPartition()->mRenderByGroup)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
|
@ -3052,9 +3052,9 @@ void LLPipeline::markMeshDirty(LLSpatialGroup* group)
|
|||
|
||||
void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
|
||||
{
|
||||
if (group && !group->isDead() && group->mSpatialPartition)
|
||||
if (group && !group->isDead() && group->getSpatialPartition())
|
||||
{
|
||||
if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
|
||||
if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD)
|
||||
{
|
||||
priority = TRUE;
|
||||
}
|
||||
|
|
@ -3629,7 +3629,7 @@ void LLPipeline::postSort(LLCamera& camera)
|
|||
|
||||
if (alpha != group->mDrawMap.end())
|
||||
{ //store alpha groups for sorting
|
||||
LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
|
||||
LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
|
||||
if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
|
||||
{
|
||||
if (bridge)
|
||||
|
|
@ -5200,7 +5200,7 @@ void LLPipeline::renderDebug()
|
|||
continue;
|
||||
}
|
||||
|
||||
LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
|
||||
LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
|
||||
|
||||
if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
|
||||
{
|
||||
|
|
@ -9988,7 +9988,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu
|
|||
LLSpatialGroup* group = *i;
|
||||
if (!group->isDead() &&
|
||||
(!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
|
||||
gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
|
||||
gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) &&
|
||||
group->mDrawMap.find(type) != group->mDrawMap.end())
|
||||
{
|
||||
pass->renderGroup(group,type,mask,texture);
|
||||
|
|
|
|||
Loading…
Reference in New Issue