Automated merge with ssh://hg.lindenlab.com/richard/viewer-interesting

meow-7.2.2
Xiaohong Bao 2013-05-23 18:26:14 -06:00
commit 774544bc51
13 changed files with 845 additions and 754 deletions

View File

@ -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)

View File

@ -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();

View File

@ -1145,7 +1145,7 @@ LLSpatialBridge::~LLSpatialBridge()
LLSpatialGroup* group = getSpatialGroup();
if (group)
{
group->mSpatialPartition->remove(this, group);
group->getSpatialPartition()->remove(this, group);
}
}

View File

@ -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];

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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
//-----------------------------------------------------------------------------------

View File

@ -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

View File

@ -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;
}

View File

@ -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:

View File

@ -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();

View File

@ -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);