From c0ba626c8009b22310b3923e8170e5db2a021253 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Mon, 15 Oct 2012 21:34:29 -0600 Subject: For SH-3333: Design and implement a new object cache system on viewer side --- indra/newview/pipeline.cpp | 50 ++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4582de805f..e06577c512 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1378,18 +1378,18 @@ S32 LLPipeline::setLightingDetail(S32 level) return mLightingDetail; } -class LLOctreeDirtyTexture : public LLOctreeTraveler +class LLOctreeDirtyTexture : public OctreeTraveler { public: const std::set& mTextures; LLOctreeDirtyTexture(const std::set& textures) : mTextures(textures) { } - virtual void visit(const LLOctreeNode* node) + virtual void visit(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) { for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -1578,11 +1578,9 @@ void LLPipeline::addPool(LLDrawPool *new_poolp) void LLPipeline::allocDrawable(LLViewerObject *vobj) { - LLDrawable *drawable = new LLDrawable(); + LLDrawable *drawable = new LLDrawable(vobj); vobj->mDrawable = drawable; - drawable->mVObjp = vobj; - //encompass completely sheared objects by taking //the most extreme point possible (<1,1,0.5>) drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); @@ -2006,7 +2004,7 @@ void check_references(LLSpatialGroup* group, LLDrawable* drawable) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - if (drawable == *i) + if (drawable == (LLDrawable*)(*i)->getDrawable()) { llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl; } @@ -2028,8 +2026,11 @@ void check_references(LLSpatialGroup* group, LLFace* face) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - check_references(drawable, face); + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(drawable) + { + check_references(drawable, face); + } } } @@ -2351,6 +2352,10 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { part->cull(camera); } + else if(part->mPartitionType == LLViewerRegion::PARTITION_VO_CACHE) + { + part->cull(camera); + } } } } @@ -2420,15 +2425,20 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) return; } + const LLVector4a* bounds = group->getBounds(); if (sMinRenderSize > 0.f && - llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize) + llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) { return; } assertInitialized(); - if (!group->mSpatialPartition->mRenderByGroup) + if(group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_VO_CACHE) + { + group->mSpatialPartition->mRegionp->addVisibleGroup(group); + } + else if (!group->mSpatialPartition->mRenderByGroup) { //render by drawable sCull->pushDrawableGroup(group); } @@ -2980,14 +2990,14 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) if (priority) { - if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) + if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) { llassert_always(!mGroupQ1Locked); mGroupQ1.push_back(group); group->setState(LLSpatialGroup::IN_BUILD_Q1); - if (group->isState(LLSpatialGroup::IN_BUILD_Q2)) + if (group->hasState(LLSpatialGroup::IN_BUILD_Q2)) { LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group); if (iter != mGroupQ2.end()) @@ -2998,7 +3008,7 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) } } } - else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) + else if (!group->hasState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) { llassert_always(!mGroupQ2Locked); mGroupQ2.push_back(group); @@ -3073,7 +3083,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) group->setVisible(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - markVisible(*i, camera); + markVisible((LLDrawable*)(*i)->getDrawable(), camera); } if (!sDelayVBUpdate) @@ -3160,8 +3170,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawablep = *i; - stateSort(drawablep, camera); + stateSort((LLDrawable*)(*i)->getDrawable(), camera); } if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) @@ -3280,7 +3289,10 @@ void forAllDrawables(LLCullResult::sg_iterator begin, { for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { - func(*j); + if((*j)->hasDrawable()) + { + func((LLDrawable*)(*j)->getDrawable()); + } } } } @@ -3508,7 +3520,7 @@ void LLPipeline::postSort(LLCamera& camera) continue; } - if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY)) + if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY)) { //no way this group is going to be drawable without a rebuild group->rebuildGeom(); } -- cgit v1.3 From 5ae116f89b8459963ccb6ae9125d94ffaa79025e Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 31 Oct 2012 17:05:53 -0600 Subject: for SH-3471: create a simplified version of octree for object cache entries. --- indra/newview/llspatialpartition.cpp | 108 ++++++---------------- indra/newview/llspatialpartition.h | 49 ++-------- indra/newview/llvieweroctree.cpp | 48 +++++++++- indra/newview/llvieweroctree.h | 39 +++++++- indra/newview/llviewerregion.cpp | 174 ++++++++++++++++++++++++----------- indra/newview/llviewerregion.h | 14 ++- indra/newview/llvocache.cpp | 77 ++++++++++++++++ indra/newview/llvocache.h | 13 +++ indra/newview/pipeline.cpp | 20 ++-- 9 files changed, 346 insertions(+), 196 deletions(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index debb790c58..e9ece331d1 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -264,11 +264,7 @@ LLSpatialGroup::~LLSpatialGroup() { llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; }*/ - if(isVisible()) - { - mSpatialPartition->mRegionp->clearVisibleGroup(this); - } - + if (gDebugGL) { gPipeline.checkReferences(this); @@ -434,16 +430,6 @@ BOOL LLSpatialGroup::isRecentlyVisible() const return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < MIN_VIS_FRAME_RANGE ; } -BOOL LLSpatialGroup::isVisible() const -{ - return mVisible[LLViewerCamera::sCurCameraID] >= LLDrawable::getCurrentFrame() ? TRUE : FALSE; -} - -void LLSpatialGroup::setVisible() -{ - mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame(); -} - void LLSpatialGroup::validate() { ll_assert_aligned(this,64); @@ -1165,12 +1151,6 @@ BOOL LLSpatialGroup::changeLOD() void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) { - if(mSpatialPartition->isVOCachePartition()) - { - LLviewerOctreeGroup::handleInsertion(node, entry); - return; - } - addObject((LLDrawable*)entry->getDrawable()); unbound(); setState(OBJECT_DIRTY); @@ -1178,10 +1158,7 @@ void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) { - if(!mSpatialPartition->isVOCachePartition()) - { - removeObject((LLDrawable*)entry->getDrawable(), TRUE); - } + removeObject((LLDrawable*)entry->getDrawable(), TRUE); LLviewerOctreeGroup::handleRemoval(node, entry); } @@ -1189,12 +1166,6 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) { setState(DEAD); - if(mSpatialPartition->isVOCachePartition()) - { - LLviewerOctreeGroup::handleDestruction(node); - return; - } - for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLViewerOctreeEntry* entry = *i; @@ -1510,8 +1481,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) //============================================== LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp) -: mRenderByGroup(render_by_group), mBridge(NULL), mRegionp(regionp) +: mRenderByGroup(render_by_group), mBridge(NULL) { + mRegionp = regionp; mOcclusionEnabled = TRUE; mDrawableType = 0; mPartitionType = LLViewerRegion::PARTITION_NONE; @@ -1521,27 +1493,14 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage = buffer_usage; mDepthMask = FALSE; mSlopRatio = 0.25f; - mInfiniteFarClip = FALSE; - mVisitedTime = 0; - - LLVector4a center, size; - center.splat(0.f); - size.splat(1.f); + mInfiniteFarClip = FALSE; - mOctree = new OctreeRoot(center,size, NULL); new LLSpatialGroup(mOctree, this); } LLSpatialPartition::~LLSpatialPartition() -{ - delete mOctree; - mOctree = NULL; -} - -BOOL LLSpatialPartition::isVOCachePartition() const -{ - return mPartitionType == LLViewerRegion::PARTITION_VO_CACHE; +{ } LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) @@ -2050,12 +2009,7 @@ BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* results, BOOL for_select) { - bool is_vo_cache_part = (mPartitionType == LLViewerRegion::PARTITION_VO_CACHE); - - if(is_vo_cache_part && mVisitedTime == LLViewerOctreeEntryData::getCurrentFrame()) - { - return 0; //no need to visit more than once per frame - } + llassert(results != NULL && for_select); #if LL_OCTREE_PARANOIA_CHECK ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); @@ -2070,19 +2024,34 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result ((LLSpatialGroup*)mOctree->getListener(0))->validate(); #endif + LLOctreeSelect selecter(&camera, results); + selecter.traverse(mOctree); - if (for_select && !is_vo_cache_part) + return 0; +} + +S32 LLSpatialPartition::cull(LLCamera &camera) +{ +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); +#endif { - LLOctreeSelect selecter(&camera, results); - selecter.traverse(mOctree); + LLFastTimer ftm(FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); } - else if (LLPipeline::sShadowRender && !is_vo_cache_part) + +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); +#endif + + if (LLPipeline::sShadowRender) { LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCullShadow culler(&camera); culler.traverse(mOctree); } - else if ((mInfiniteFarClip || !LLPipeline::sUseFarClip) && !is_vo_cache_part) + else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) { LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCullNoFarClip culler(&camera); @@ -2090,11 +2059,6 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result } else { - if(is_vo_cache_part) - { - mVisitedTime = LLViewerOctreeEntryData::getCurrentFrame(); - } - LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCull culler(&camera); culler.traverse(mOctree); @@ -4663,21 +4627,3 @@ void LLCullResult::assertDrawMapsEmpty() } } -LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) : LLSpatialPartition(0, FALSE, 0, regionp) -{ - mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; -} - -void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry) -{ - llassert(entry->hasVOCacheEntry()); - - mOctree->insert(entry); -} - -void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry) -{ - entry->getVOCacheEntry()->setGroup(NULL); - - llassert(!entry->getGroup()); -} diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index dd189d751d..079c0f58f0 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -45,6 +45,7 @@ #define SG_STATE_INHERIT_MASK (OCCLUDED) #define SG_INITIAL_STATE_MASK (DIRTY | GEOM_DIRTY) +class LLViewerOctreePartition; class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; @@ -225,10 +226,7 @@ public: typedef std::map draw_map_t; typedef std::vector > buffer_list_t; typedef std::map buffer_texture_map_t; - typedef std::map buffer_map_t; - - typedef LLOctreeNode::element_iter element_iter; - typedef LLOctreeNode::element_list element_list; + typedef std::map buffer_map_t; struct CompareDistanceGreater { @@ -308,9 +306,7 @@ public: BOOL addObject(LLDrawable *drawablep); BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE); BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group - BOOL isVisible() const; BOOL isRecentlyVisible() const; - void setVisible(); void shift(const LLVector4a &offset); void checkOcclusion(); //read back last occlusion query (if any) void doOcclusion(LLCamera* camera); //issue occlusion query @@ -325,14 +321,7 @@ public: void setState(U32 state) {mState |= state;} void dirtyGeom() { setState(GEOM_DIRTY); } - void dirtyMesh() { setState(MESH_DIRTY); } - - //octree wrappers to make code more readable - element_list& getData() { return mOctreeNode->getData(); } - element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } - element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } - U32 getElementCount() const { return mOctreeNode->getElementCount(); } - bool isEmpty() const { return mOctreeNode->isEmpty(); } + void dirtyMesh() { setState(MESH_DIRTY); } void drawObjectBox(LLColor4 col); @@ -404,8 +393,7 @@ public: U32 mBufferUsage; draw_map_t mDrawMap; - - S32 mVisible[LLViewerCamera::NUM_CAMERAS]; + F32 mDistance; F32 mDepth; F32 mLastUpdateDistance; @@ -428,7 +416,7 @@ public: virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); }; -class LLSpatialPartition: public LLGeometryManager +class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManager { public: LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage, LLViewerRegion* regionp); @@ -458,7 +446,8 @@ public: virtual void rebuildMesh(LLSpatialGroup* group); BOOL visibleObjectsInFrustum(LLCamera& camera); - S32 cull(LLCamera &camera, std::vector* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum + /*virtual*/ S32 cull(LLCamera &camera); // Cull on arbitrary frustum + S32 cull(LLCamera &camera, std::vector* results, BOOL for_select); // Cull on arbitrary frustum BOOL isVisible(const LLVector3& v); bool isHUDPartition() ; @@ -473,26 +462,21 @@ public: void resetVertexBuffers(); BOOL isOcclusionEnabled(); BOOL getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax); - BOOL isVOCachePartition() const; - + public: - OctreeNode* mOctree; 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 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 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 - U32 mDrawableType; - U32 mPartitionType; - U32 mVisitedTime; - LLViewerRegion* mRegionp; // the region this partition belongs to. + BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering }; // class for creating bridges between spatial partitions @@ -638,19 +622,6 @@ public: LLVoidWaterPartition(LLViewerRegion* regionp); }; -//spatial partition for hole and edge water (implemented in LLVOWater.cpp) -class LLVOCachePartition : public LLSpatialPartition -{ -public: - LLVOCachePartition(LLViewerRegion* regionp); - - void addEntry(LLViewerOctreeEntry* entry); - void removeEntry(LLViewerOctreeEntry* entry); - - virtual void getGeometry(LLSpatialGroup* group) { } - virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } -}; - //spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp) class LLTerrainPartition : public LLSpatialPartition { diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 05f977036c..143f2a6819 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" #include "llvieweroctree.h" +#include "llviewerregion.h" //----------------------------------------------------------------------------------- //static variables definitions @@ -324,6 +325,10 @@ void LLViewerOctreeEntryData::setVisible() const LLviewerOctreeGroup::~LLviewerOctreeGroup() { + if(LLViewerRegion::sCurRegionp && isVisible()) + { + LLViewerRegion::sCurRegionp->clearVisibleGroup(this); + } } LLviewerOctreeGroup::LLviewerOctreeGroup(OctreeNode* node) : @@ -482,8 +487,10 @@ void LLviewerOctreeGroup::handleDestruction(const TreeNode* node) if (obj && obj->getGroup() == this) { obj->nullGroup(); + //obj->setGroup(NULL); } } + mOctreeNode = NULL; } //virtual @@ -500,8 +507,17 @@ void LLviewerOctreeGroup::handleStateChange(const TreeNode* node) //virtual void LLviewerOctreeGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { - llerrs << "can not access here. It is an abstract class." << llendl; + if (child->getListenerCount() == 0) + { + new LLviewerOctreeGroup(child); + } + else + { + OCT_ERRS << "LLSpatialGroup redundancy detected." << llendl; + } + unbound(); + //((LLviewerOctreeGroup*)child->getListener(0))->unbound(); } @@ -589,7 +605,35 @@ bool LLviewerOctreeGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4 //virtual BOOL LLviewerOctreeGroup::isVisible() const { - return TRUE; + return mVisible[LLViewerCamera::sCurCameraID] >= LLViewerOctreeEntryData::getCurrentFrame() ? TRUE : FALSE; +} + +//virtual +BOOL LLviewerOctreeGroup::isRecentlyVisible() const +{ + return FALSE; +} + +void LLviewerOctreeGroup::setVisible() +{ + mVisible[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); +} +//----------------------------------------------------------------------------------- +//class LLViewerOctreePartition definitions +//----------------------------------------------------------------------------------- +LLViewerOctreePartition::LLViewerOctreePartition() : mRegionp(NULL) +{ + LLVector4a center, size; + center.splat(0.f); + size.splat(1.f); + + mOctree = new OctreeRoot(center,size, NULL); +} + +LLViewerOctreePartition::~LLViewerOctreePartition() +{ + delete mOctree; + mOctree = NULL; } //----------------------------------------------------------------------------------- diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index c063e96ea5..498ec3e75d 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -37,8 +37,9 @@ #include "llvector4a.h" #include "llquaternion.h" #include "lloctree.h" -#include "llcamera.h" +#include "llviewercamera.h" +class LLViewerRegion; class LLViewerOctreeEntryData; class LLviewerOctreeGroup; class LLViewerOctreeEntry; @@ -181,6 +182,9 @@ public: }; public: + typedef LLOctreeNode::element_iter element_iter; + typedef LLOctreeNode::element_list element_list; + LLviewerOctreeGroup(OctreeNode* node); LLviewerOctreeGroup(const LLviewerOctreeGroup& rhs) { @@ -203,8 +207,10 @@ public: virtual void unbound(); virtual void rebound(); - virtual BOOL isVisible() const; - virtual BOOL isRecentlyVisible() const = 0; + void setVisible(); + BOOL isVisible() const; + virtual BOOL isRecentlyVisible() const; + bool isEmpty() const { return mOctreeNode->isEmpty(); } U32 getState() {return mState; } bool isDirty() const {return mState & DIRTY;} @@ -228,20 +234,43 @@ public: const LLVector4a* getObjectBounds() const {return mObjectBounds;} const LLVector4a* getObjectExtents() const {return mObjectExtents;} + //octree wrappers to make code more readable + element_list& getData() { return mOctreeNode->getData(); } + element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } + element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } + U32 getElementCount() const { return mOctreeNode->getElementCount(); } + private: virtual bool boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut); protected: U32 mState; - OctreeNode* mOctreeNode; - + OctreeNode* mOctreeNode; + 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 +public: + S32 mVisible[LLViewerCamera::NUM_CAMERAS]; }LL_ALIGN_POSTFIX(16); +class LLViewerOctreePartition +{ +public: + LLViewerOctreePartition(); + virtual ~LLViewerOctreePartition(); + + // Cull on arbitrary frustum + virtual S32 cull(LLCamera &camera) = 0; + +public: + U32 mPartitionType; + OctreeNode* mOctree; + LLViewerRegion* mRegionp; // the region this partition belongs to. +}; + class LLViewerOctreeCull : public OctreeTraveler { public: diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 0c0522d32f..1adab15d70 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -86,6 +86,8 @@ const F32 CAP_REQUEST_TIMEOUT = 18; // Even though we gave up on login, keep trying for caps after we are logged in: const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; +LLViewerRegion* LLViewerRegion::sCurRegionp = NULL; + typedef std::map CapabilityMap; class LLViewerRegionImpl { @@ -139,7 +141,7 @@ public: LLVOCacheEntry::vocache_entry_set_t mWaitingSet; //entries waiting for LLDrawable to be generated. LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //visible root entries of a linked set. std::set< LLPointer > mDummyEntries; //dummy vo cache entries, for LLSpatialBridge use. - std::set< LLSpatialGroup* > mVisibleGroups; //visible llspatialgroup + std::set< LLviewerOctreeGroup* > mVisibleGroups; //visible llspatialgroup LLVOCachePartition* mVOCachePartition; // time? @@ -165,7 +167,7 @@ public: LLCapabilityListener mCapabilityListener; //spatial partitions for objects in this region - std::vector mObjectPartition; + std::vector mObjectPartition; }; // support for secondlife:///app/region/{REGION} SLapps @@ -345,7 +347,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE - mImpl->mVOCachePartition = (LLVOCachePartition*)getSpatialPartition(PARTITION_VO_CACHE); + mImpl->mVOCachePartition = getVOCachePartition(); } @@ -384,12 +386,12 @@ LLViewerRegion::~LLViewerRegion() delete mParcelOverlay; delete mImpl->mLandp; delete mImpl->mEventPoll; - LLHTTPSender::clearSender(mImpl->mHost); - - saveObjectCache(); + LLHTTPSender::clearSender(mImpl->mHost); std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); + saveObjectCache(); + delete mImpl; mImpl = NULL; } @@ -865,13 +867,13 @@ void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* d entry->setState(LLVOCacheEntry::INACTIVE); } -void LLViewerRegion::addVisibleGroup(LLSpatialGroup* group) +void LLViewerRegion::addVisibleGroup(LLviewerOctreeGroup* group) { - if(mDead || group->isEmpty() || group->isDead()) + if(mDead || group->isEmpty()) { return; } - + group->setVisible(); mImpl->mVisibleGroups.insert(group); } @@ -909,7 +911,7 @@ void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry) mImpl->mVisibleEntries.insert(entry); } -void LLViewerRegion::clearVisibleGroup(LLSpatialGroup* group) +void LLViewerRegion::clearVisibleGroup(LLviewerOctreeGroup* group) { if(mDead) { @@ -920,44 +922,18 @@ void LLViewerRegion::clearVisibleGroup(LLSpatialGroup* group) mImpl->mVisibleGroups.erase(group); } - -BOOL LLViewerRegion::idleUpdate(F32 max_update_time) -{ - LLTimer update_timer; - - // did_update returns TRUE if we did at least one significant update - BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); - if (mParcelOverlay) - { - // Hopefully not a significant time sink... - mParcelOverlay->idleUpdate(); - } - - if(update_timer.getElapsedTimeF32() > max_update_time) - { - return did_update; - } - - //kill invisible objects - std::vector delete_list; - for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.begin(); - iter != mImpl->mActiveSet.end(); ++iter) - { - if(!(*iter)->isRecentlyVisible()) - { - killObject((*iter), delete_list); - } - } - for(S32 i = 0; i < delete_list.size(); i++) +//return time left +F32 LLViewerRegion::addLinkedSetChildren(F32 max_time, S32& max_num_objects) +{ + if(mImpl->mVisibleEntries.empty()) { - gObjectList.killObject(delete_list[i]->getVObj()); + return max_time; } - delete_list.clear(); + LLTimer update_timer; bool timeout = false; - S32 new_object_count = 64; //minimum number of new objects to be added - //add childrens of visible objects to the rendering pipeline + for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();) { LLVOCacheEntry* entry = *iter; @@ -968,9 +944,9 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) { addNewObject(child); - if(new_object_count-- < 0 && update_timer.getElapsedTimeF32() > max_update_time) + if(max_num_objects-- < 0 && update_timer.getElapsedTimeF32() > max_time) { - timeout = true; + timeout = true; //timeout break; } } @@ -982,7 +958,10 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) { mImpl->mDummyEntries.erase(entry); } - + } + + if(!timeout) + { iter = mImpl->mVisibleEntries.erase(iter); } else @@ -990,17 +969,28 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) break; //timeout } } + if(timeout) { - mImpl->mVisibleGroups.clear(); - return did_update; + return -1.f; } + return max_time - update_timer.getElapsedTimeF32(); //time left +} - //add objects in the visible groups to the rendering pipeline - std::set< LLSpatialGroup* >::iterator group_iter = mImpl->mVisibleGroups.begin(); +F32 LLViewerRegion::addVisibleObjects(F32 max_time, S32& max_num_objects) +{ + if(mImpl->mVisibleGroups.empty()) + { + return max_time; + } + + LLTimer update_timer; + bool timeout = false; + + std::set< LLviewerOctreeGroup* >::iterator group_iter = mImpl->mVisibleGroups.begin(); while(group_iter != mImpl->mVisibleGroups.end()) { - LLSpatialGroup* group = *group_iter; + LLviewerOctreeGroup* group = *group_iter; if(!group->getOctreeNode() || group->isEmpty()) { mImpl->mVisibleGroups.erase(group_iter); @@ -1009,7 +999,7 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) } std::vector entry_list; - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + for (LLviewerOctreeGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { //group data contents could change during creating new objects, so copy all contents first. entry_list.push_back(*i); @@ -1028,7 +1018,7 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) else if(vo_entry->isState(LLVOCacheEntry::INACTIVE)) { addNewObject(vo_entry); - if(new_object_count-- < 0 && update_timer.getElapsedTimeF32() > max_update_time) + if(max_num_objects-- < 0 && update_timer.getElapsedTimeF32() > max_time) { timeout = true; break; @@ -1044,12 +1034,75 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) } mImpl->mVisibleGroups.erase(group); group_iter = mImpl->mVisibleGroups.begin(); + } + + if(timeout) + { + return -1.0f; } - mImpl->mVisibleGroups.clear(); + return max_time - update_timer.getElapsedTimeF32(); +} + +BOOL LLViewerRegion::idleUpdate(F32 max_update_time) +{ + LLTimer update_timer; + // did_update returns TRUE if we did at least one significant update + BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); + + if (mParcelOverlay) + { + // Hopefully not a significant time sink... + mParcelOverlay->idleUpdate(); + } + + max_update_time -= update_timer.getElapsedTimeF32(); + if(max_update_time < 0.f) + { + return did_update; + } + + sCurRegionp = this; + + //kill invisible objects + max_update_time = killInvisibleObjects(max_update_time); + + S32 new_object_count = 64; //minimum number of new objects to be added + + //add childrens of visible objects to the rendering pipeline + max_update_time = addLinkedSetChildren(max_update_time, new_object_count); + + //add objects in the visible groups to the rendering pipeline + if(max_update_time > 0.f) + { + addVisibleObjects(max_update_time, new_object_count); + } + + mImpl->mVisibleGroups.clear(); + sCurRegionp = NULL; return did_update; } +F32 LLViewerRegion::killInvisibleObjects(F32 max_time) +{ + std::vector delete_list; + for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.begin(); + iter != mImpl->mActiveSet.end(); ++iter) + { + if(!(*iter)->isRecentlyVisible()) + { + killObject((*iter), delete_list); + } + } + for(S32 i = 0; i < delete_list.size(); i++) + { + gObjectList.killObject(delete_list[i]->getVObj()); + } + delete_list.clear(); + + return max_time; +} + void LLViewerRegion::killObject(LLVOCacheEntry* entry, std::vector& delete_list) { //kill the object. @@ -2189,9 +2242,18 @@ void LLViewerRegion::logActiveCapabilities() const LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) { - if (type < mImpl->mObjectPartition.size()) + if (type < mImpl->mObjectPartition.size() && type < PARTITION_VO_CACHE) + { + return (LLSpatialPartition*)mImpl->mObjectPartition[type]; + } + return NULL; +} + +LLVOCachePartition* LLViewerRegion::getVOCachePartition() +{ + if(PARTITION_VO_CACHE < mImpl->mObjectPartition.size()) { - return mImpl->mObjectPartition[type]; + return (LLVOCachePartition*)mImpl->mObjectPartition[PARTITION_VO_CACHE]; } return NULL; } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 17654a8bc7..86d3ee0d8c 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -69,6 +69,8 @@ class LLBBox; class LLSpatialGroup; class LLDrawable; class LLViewerRegionImpl; +class LLviewerOctreeGroup; +class LLVOCachePartition; class LLViewerRegion: public LLCapabilityProvider // implements this interface { @@ -85,7 +87,7 @@ public: PARTITION_GRASS, PARTITION_VOLUME, PARTITION_BRIDGE, - PARTITION_HUD_PARTICLE, + PARTITION_HUD_PARTICLE, PARTITION_VO_CACHE, PARTITION_NONE, NUM_PARTITIONS @@ -218,12 +220,12 @@ public: F32 getWidth() const { return mWidth; } BOOL idleUpdate(F32 max_update_time); - void addVisibleGroup(LLSpatialGroup* group); + void addVisibleGroup(LLviewerOctreeGroup* group); void addVisibleCacheEntry(LLVOCacheEntry* entry); void addActiveCacheEntry(LLVOCacheEntry* entry); void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep); void killCacheEntry(U32 local_id); //physically delete the cache entry - void clearVisibleGroup(LLSpatialGroup* group); + void clearVisibleGroup(LLviewerOctreeGroup* group); // Like idleUpdate, but forces everything to complete regardless of // how long it takes. @@ -333,6 +335,7 @@ public: U32 getNumOfActiveCachedObjects() const; LLSpatialPartition* getSpatialPartition(U32 type); + LLVOCachePartition* getVOCachePartition(); bool objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const; bool childrenObjectReturnable( const std::vector& boxes ) const; @@ -350,6 +353,10 @@ private: void replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry); void killCacheEntry(LLVOCacheEntry* entry); //physically delete the cache entry + F32 killInvisibleObjects(F32 max_time); + F32 addLinkedSetChildren(F32 max_time, S32& max_num_objects); + F32 addVisibleObjects(F32 max_time, S32& max_num_objects); + public: struct CompareDistance { @@ -384,6 +391,7 @@ public: LLDynamicArray mMapAvatars; LLDynamicArray mMapAvatarIDs; + static LLViewerRegion* sCurRegionp; private: LLViewerRegionImpl * mImpl; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index f389867484..d4938fd216 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -31,6 +31,7 @@ #include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "lldrawable.h" +#include "llviewerregion.h" BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) { @@ -355,6 +356,82 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const return success ; } +//------------------------------------------------------------------- +//LLVOCachePartition +//------------------------------------------------------------------- +LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) +{ + mRegionp = regionp; + mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; + mVisitedTime = 0; + + new LLviewerOctreeGroup(mOctree); +} + +void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry) +{ + llassert(entry->hasVOCacheEntry()); + + mOctree->insert(entry); +} + +void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry) +{ + entry->getVOCacheEntry()->setGroup(NULL); + + llassert(!entry->getGroup()); +} + +class LLVOCacheOctreeCull : public LLViewerOctreeCull +{ +public: + LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp) : LLViewerOctreeCull(camera), mRegionp(regionp) {} + + virtual S32 frustumCheck(const LLviewerOctreeGroup* group) + { + S32 res = AABBInFrustumNoFarClipGroupBounds(group); + if (res != 0) + { + res = llmin(res, AABBSphereIntersectGroupExtents(group)); + } + return res; + } + + virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) + { + S32 res = AABBInFrustumNoFarClipObjectBounds(group); + if (res != 0) + { + res = llmin(res, AABBSphereIntersectObjectExtents(group)); + } + return res; + } + + virtual void processGroup(LLviewerOctreeGroup* base_group) + { + mRegionp->addVisibleGroup(base_group); + } + +private: + LLViewerRegion* mRegionp; +}; + +S32 LLVOCachePartition::cull(LLCamera &camera) +{ + if(mVisitedTime == LLViewerOctreeEntryData::getCurrentFrame()) + { + return 0; //already visited. + } + mVisitedTime = LLViewerOctreeEntryData::getCurrentFrame(); + + ((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound(); + + LLVOCacheOctreeCull culler(&camera, mRegionp); + culler.traverse(mOctree); + + return 0; +} + //------------------------------------------------------------------- //LLVOCache //------------------------------------------------------------------- diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 2228e3e43b..675c12a3eb 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -98,6 +98,19 @@ protected: std::vector mChildrenList; //children entries in a linked set. }; +class LLVOCachePartition : public LLViewerOctreePartition +{ +public: + LLVOCachePartition(LLViewerRegion* regionp); + + void addEntry(LLViewerOctreeEntry* entry); + void removeEntry(LLViewerOctreeEntry* entry); + /*virtual*/ S32 cull(LLCamera &camera); + +private: + U32 mVisitedTime; +}; + // //Note: LLVOCache is not thread-safe // diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e06577c512..850714f676 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -86,6 +86,7 @@ #include "llviewerregion.h" // for audio debugging. #include "llviewerwindow.h" // For getSpinAxis #include "llvoavatarself.h" +#include "llvocache.h" #include "llvoground.h" #include "llvosky.h" #include "llvotree.h" @@ -2352,12 +2353,15 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { part->cull(camera); } - else if(part->mPartitionType == LLViewerRegion::PARTITION_VO_CACHE) - { - part->cull(camera); - } } } + + //scan the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->cull(camera); + } } if (bound_shader) @@ -2433,12 +2437,8 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) } assertInitialized(); - - if(group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_VO_CACHE) - { - group->mSpatialPartition->mRegionp->addVisibleGroup(group); - } - else if (!group->mSpatialPartition->mRenderByGroup) + + if (!group->mSpatialPartition->mRenderByGroup) { //render by drawable sCull->pushDrawableGroup(group); } -- cgit v1.3 From 21409a3aaaef71102195d65fc35cebdb5d941a26 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Fri, 30 Nov 2012 22:50:06 -0700 Subject: for SH-3350 and SH-3353: Report frame-to-frame visual deltas as an LLStat --- .../class1/interface/onetexturefilterF.glsl | 49 ++++++ .../class1/interface/onetexturefilterV.glsl | 38 +++++ .../class1/interface/twotexturecompareF.glsl | 16 +- indra/newview/llscenemonitor.cpp | 188 ++++++++++++++------- indra/newview/llscenemonitor.h | 17 +- indra/newview/llspatialpartition.cpp | 22 ++- indra/newview/llspatialpartition.h | 2 + indra/newview/llviewershadermgr.cpp | 17 ++ indra/newview/llviewershadermgr.h | 4 +- indra/newview/pipeline.cpp | 5 +- 10 files changed, 271 insertions(+), 87 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/onetexturefilterV.glsl (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl new file mode 100644 index 0000000000..f1400c9b44 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl @@ -0,0 +1,49 @@ +/** + * @file onetexturefilterF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform sampler2D tex0; +uniform float tolerance; + +VARYING vec2 vary_texcoord0; + +void main() +{ + frag_color = texture2D(tex0, vary_texcoord0.xy); + + if(frag_color[0] + frag_color[1] + frag_color[2] < tolerance) + { + discard; + } + else + { + frag_color[3] = 0.95f; + } +} diff --git a/indra/newview/app_settings/shaders/class1/interface/onetexturefilterV.glsl b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterV.glsl new file mode 100644 index 0000000000..a33ef7e92c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterV.glsl @@ -0,0 +1,38 @@ +/** + * @file onetexturefilterV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; +ATTRIBUTE vec2 texcoord0; + +VARYING vec2 vary_texcoord0; + +void main() +{ + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = texcoord0; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl index 336ca21b96..050114b37e 100644 --- a/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl @@ -37,19 +37,5 @@ VARYING vec2 vary_texcoord1; void main() { - frag_color = texture2D(tex0, vary_texcoord0.xy) - texture2D(tex1, vary_texcoord0.xy); - - if(frag_color[0] < 0.f) - { - frag_color[0] = -frag_color[0]; - } - if(frag_color[1] < 0.f) - { - frag_color[1] = -frag_color[1]; - } - if(frag_color[2] < 0.f) - { - frag_color[2] = -frag_color[2]; - } - frag_color[3] = 0.95f; + frag_color = abs(texture2D(tex0, vary_texcoord0.xy) - texture2D(tex1, vary_texcoord0.xy)); } diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 0730281d85..adeada04ca 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -36,18 +36,24 @@ #include "llappviewer.h" #include "llwindow.h" #include "llpointer.h" +#include "llspatialpartition.h" LLSceneMonitorView* gSceneMonitorView = NULL; LLSceneMonitor::LLSceneMonitor() : mEnabled(FALSE), - mDiff(NULL), + mDiff(NULL), + mDiffResult(0.f), + mDiffTolerance(0.1f), mCurTarget(NULL), - mNeedsUpdateDiff(FALSE), - mDebugViewerVisible(FALSE) + mNeedsUpdateDiff(FALSE), + mHasNewDiff(FALSE), + mHasNewQueryResult(FALSE), + mDebugViewerVisible(FALSE), + mQueryObject(0) { mFrames[0] = NULL; - mFrames[1] = NULL; + mFrames[1] = NULL; } LLSceneMonitor::~LLSceneMonitor() @@ -69,6 +75,15 @@ void LLSceneMonitor::reset() mFrames[0] = NULL; mFrames[1] = NULL; mDiff = NULL; + mCurTarget = NULL; + + unfreezeScene(); + + if(mQueryObject > 0) + { + release_occlusion_query_object_name(mQueryObject); + mQueryObject = 0; + } } void LLSceneMonitor::setDebugViewerVisible(BOOL visible) @@ -108,28 +123,6 @@ bool LLSceneMonitor::preCapture() return false; } - if (LLStartUp::getStartupState() < STATE_STARTED) - { - return false; - } - - if(LLAppViewer::instance()->logoutRequestSent()) - { - return false; - } - - if(gWindowResized || gHeadlessClient || gTeleportDisplay || gRestoreGL || gDisconnected) - { - return false; - } - - if ( !gViewerWindow->getActive() - || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() ) - { - return false; - } - if(timer.getElapsedTimeF32() < 1.0f) { return false; @@ -174,12 +167,6 @@ bool LLSceneMonitor::preCapture() return true; } -void LLSceneMonitor::postCapture() -{ - mCurTarget = NULL; - mNeedsUpdateDiff = TRUE; -} - void LLSceneMonitor::freezeAvatar(LLCharacter* avatarp) { mAvatarPauseHandles.push_back(avatarp->requestPause()); @@ -207,19 +194,14 @@ void LLSceneMonitor::unfreezeScene() gSavedSettings.setBOOL("FreezeTime", FALSE); } -LLRenderTarget* LLSceneMonitor::getDiffTarget() const -{ - return mDiff; -} - void LLSceneMonitor::capture() { - static U32 count = 0; - if(count == gFrameCount) + static U32 last_capture_time = 0; + if(last_capture_time == gFrameCount) { return; } - count = gFrameCount; + last_capture_time = gFrameCount; preCapture(); @@ -239,7 +221,8 @@ void LLSceneMonitor::capture() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, old_FBO); - postCapture(); + mCurTarget = NULL; + mNeedsUpdateDiff = TRUE; } void LLSceneMonitor::compare() @@ -248,6 +231,7 @@ void LLSceneMonitor::compare() { return; } + mNeedsUpdateDiff = FALSE; if(!mFrames[0] || !mFrames[1]) { @@ -258,11 +242,6 @@ void LLSceneMonitor::compare() return; //size does not match } - if (!LLGLSLShader::sNoFixedFunction) - { - return; - } - S32 width = gViewerWindow->getWindowWidthRaw(); S32 height = gViewerWindow->getWindowHeightRaw(); if(!mDiff) @@ -274,9 +253,10 @@ void LLSceneMonitor::compare() { mDiff->resize(width, height, GL_RGBA); } + mDiff->bindTarget(); mDiff->clear(); - + gTwoTextureCompareProgram.bind(); gGL.getTexUnit(0)->activate(); @@ -288,21 +268,108 @@ void LLSceneMonitor::compare() gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->bind(mFrames[1]); gGL.getTexUnit(1)->activate(); - + gl_rect_2d_simple_tex(width, height); - mDiff->flush(); + mDiff->flush(); gTwoTextureCompareProgram.unbind(); - + gGL.getTexUnit(0)->disable(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->disable(); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); - mNeedsUpdateDiff = FALSE; + mHasNewDiff = TRUE; + + //send out the query request. + queryDiff(); +} + +void LLSceneMonitor::queryDiff() +{ + if(mDebugViewerVisible) + { + return; + } + + calcDiffAggregate(); +} + +//calculate Diff aggregate information in GPU, and enable gl occlusion query to capture it. +void LLSceneMonitor::calcDiffAggregate() +{ + if(!mHasNewDiff && !mDebugViewerVisible) + { + return; + } + + if(!mQueryObject) + { + mQueryObject = get_new_occlusion_query_object_name(); + } + + LLGLDepthTest depth(true, false, GL_ALWAYS); + if(!mDebugViewerVisible) + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } + + LLGLSLShader* cur_shader = NULL; + + cur_shader = LLGLSLShader::sCurBoundShaderPtr; + gOneTextureFilterProgram.bind(); + gOneTextureFilterProgram.uniform1f("tolerance", mDiffTolerance); + + if(mHasNewDiff) + { + glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mQueryObject); + } + + gl_draw_scaled_target(0, 0, mDiff->getWidth() * 0.5f, mDiff->getHeight() * 0.5f, mDiff); + + if(mHasNewDiff) + { + glEndQueryARB(GL_SAMPLES_PASSED_ARB); + mHasNewDiff = FALSE; + mHasNewQueryResult = TRUE; + } + + gOneTextureFilterProgram.unbind(); + + if(cur_shader != NULL) + { + cur_shader->bind(); + } + + if(!mDebugViewerVisible) + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } } +void LLSceneMonitor::fetchQueryResult() +{ + if(!mHasNewQueryResult) + { + return; + } + mHasNewQueryResult = FALSE; + + GLuint available = 0; + glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_AVAILABLE_ARB, &available); + if(!available) + { + return; + } + + GLuint count = 0; + glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_ARB, &count); + + mDiffResult = count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * 0.25f); + + //llinfos << count << " : " << mDiffResult << llendl; +} //------------------------------------------------------------------------------------------------------------- //definition of class LLSceneMonitorView //------------------------------------------------------------------------------------------------------------- @@ -330,27 +397,26 @@ void LLSceneMonitorView::setVisible(BOOL visible) void LLSceneMonitorView::draw() { - if (!LLGLSLShader::sNoFixedFunction) - { - return; - } - LLRenderTarget* target = LLSceneMonitor::getInstance()->getDiffTarget(); + const LLRenderTarget* target = LLSceneMonitor::getInstance()->getDiffTarget(); if(!target) { return; } - S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.5f); - S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.5f); + S32 height = target->getHeight() * 0.5f; + S32 width = target->getWidth() * 0.5f; + //S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.5f); + //S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.5f); LLRect new_rect; new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); setRect(new_rect); - //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - //gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); + //draw background + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); - gl_draw_scaled_target(0, 0, getRect().getWidth(), getRect().getHeight(), target); + LLSceneMonitor::getInstance()->calcDiffAggregate(); LLView::draw(); } diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index 648429f97b..db5ac3eeef 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -48,8 +48,14 @@ public: void capture(); //capture the main frame buffer void compare(); //compare the stored two buffers. + void queryDiff(); + void fetchQueryResult(); + void calcDiffAggregate(); + void setDiffTolerance(F32 tol) {mDiffTolerance = tol;} - LLRenderTarget* getDiffTarget() const; + const LLRenderTarget* getDiffTarget() const {return mDiff;} + F32 getDiffTolerance() const {return mDiffTolerance;} + F32 getDiffResult() const { return mDiffResult;} bool isEnabled()const {return mEnabled;} private: @@ -57,17 +63,22 @@ private: void unfreezeScene(); void reset(); bool preCapture(); - void postCapture(); - + private: BOOL mEnabled; BOOL mNeedsUpdateDiff; + BOOL mHasNewDiff; + BOOL mHasNewQueryResult; BOOL mDebugViewerVisible; LLRenderTarget* mFrames[2]; LLRenderTarget* mDiff; LLRenderTarget* mCurTarget; + GLuint mQueryObject; //used for glQuery + F32 mDiffResult; //aggregate results of mDiff. + F32 mDiffTolerance; //pixels are filtered out when R+G+B < mDiffTolerance + std::vector mAvatarPauseHandles; }; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e9ece331d1..b7694074a5 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -126,6 +126,16 @@ protected: 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 void sg_assert(BOOL expr) @@ -283,7 +293,7 @@ LLSpatialGroup::~LLSpatialGroup() { if (mOcclusionQuery[i]) { - sQueryPool.release(mOcclusionQuery[i]); + release_occlusion_query_object_name(mOcclusionQuery[i]); } } } @@ -879,7 +889,7 @@ void LLSpatialGroup::setOcclusionState(U32 state, S32 mode) if ((state & DISCARD_QUERY) && mOcclusionQuery[i]) { - sQueryPool.release(mOcclusionQuery[i]); + release_occlusion_query_object_name(mOcclusionQuery[i]); mOcclusionQuery[i] = 0; } } @@ -890,7 +900,7 @@ void LLSpatialGroup::setOcclusionState(U32 state, S32 mode) mOcclusionState[LLViewerCamera::sCurCameraID] |= state; if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) { - sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + release_occlusion_query_object_name(mOcclusionQuery[LLViewerCamera::sCurCameraID]); mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; } } @@ -1237,7 +1247,7 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) { if (mOcclusionQuery[i]) { - sQueryPool.release(mOcclusionQuery[i]); + release_occlusion_query_object_name(mOcclusionQuery[i]); mOcclusionQuery[i] = 0; } } @@ -1318,7 +1328,7 @@ void LLSpatialGroup::checkOcclusion() } else if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) { //delete the query to avoid holding onto hundreds of pending queries - sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + release_occlusion_query_object_name(mOcclusionQuery[LLViewerCamera::sCurCameraID]); mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; } @@ -1390,7 +1400,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) { LLFastTimer t(FTM_OCCLUSION_ALLOCATE); - mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = get_new_occlusion_query_object_name(); } // Depth clamp all water to avoid it being culled as a result of being diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 079c0f58f0..57e986fb80 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -58,6 +58,8 @@ 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 { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5295573709..1aa36eafee 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -79,6 +79,7 @@ LLGLSLShader gSplatTextureRectProgram; LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; LLGLSLShader gTwoTextureCompareProgram; +LLGLSLShader gOneTextureFilterProgram; LLGLSLShader gOneTextureNoColorProgram; LLGLSLShader gDebugProgram; LLGLSLShader gClipProgram; @@ -674,6 +675,7 @@ void LLViewerShaderMgr::unloadShaders() gGlowCombineFXAAProgram.unload(); gTwoTextureAddProgram.unload(); gTwoTextureCompareProgram.unload(); + gOneTextureFilterProgram.unload(); gOneTextureNoColorProgram.unload(); gSolidColorProgram.unload(); @@ -2724,6 +2726,21 @@ BOOL LLViewerShaderMgr::loadShadersInterface() } } + if (success) + { + gOneTextureFilterProgram.mName = "One Texture Filter Shader"; + gOneTextureFilterProgram.mShaderFiles.clear(); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB)); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOneTextureFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gOneTextureFilterProgram.createShader(NULL, NULL); + if (success) + { + gOneTextureFilterProgram.bind(); + gOneTextureFilterProgram.uniform1i("tex0", 0); + } + } + if (success) { gOneTextureNoColorProgram.mName = "One Texture No Color Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 8a706daa8f..3e7c615f23 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -235,7 +235,9 @@ extern LLGLSLShader gAlphaMaskProgram; extern LLGLSLShader gTwoTextureAddProgram; //output tex0[tc0] - tex1[tc1] extern LLGLSLShader gTwoTextureCompareProgram; - +//discard some fragments based on user-set color tolerance +extern LLGLSLShader gOneTextureFilterProgram; + extern LLGLSLShader gOneTextureNoColorProgram; //object shaders diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 850714f676..d8af7a5cfb 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -112,6 +112,7 @@ #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindingcharacters.h" #include "llpathfindingpathtool.h" +#include "llscenemonitor.h" #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -3161,7 +3162,9 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } - postSort(camera); + postSort(camera); + + LLSceneMonitor::getInstance()->fetchQueryResult(); } void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) -- cgit v1.3