diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index ad659baa9e9f7861143053c1f64a2d7711b12a91..a5045e6a4c094980cb8063352e59ded51995a624 100755
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -265,12 +265,6 @@ BOOL LLSpatialGroup::isHUDGroup()
 	return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; 
 }
 
-BOOL LLSpatialGroup::isRecentlyVisible() const
-{
-	const S32 MIN_VIS_FRAME_RANGE = 2;
-	return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < MIN_VIS_FRAME_RANGE ;
-}
-
 void LLSpatialGroup::validate()
 {
 	ll_assert_aligned(this,64);
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 05ed70ab59eabf9b1ccbfa68e07cfefa8005628c..6202fb11cbf28060eb4e3f0de0e2d8d3478e3ccf 100755
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -290,7 +290,6 @@ class LLSpatialGroup : public LLOcclusionCullingGroup
 	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 isRecentlyVisible() const;
 	void shift(const LLVector4a &offset);
 	void destroyGL(bool keep_occlusion = false);
 	
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index bba3d26e09e3f4bd7d1e158709b16dc0d9262203..9b8a3c92699af9508a3aa9f9dedd9ce3fff9acd5 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -853,6 +853,12 @@ BOOL LLOcclusionCullingGroup::needsUpdate()
 	return (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
 }
 
+BOOL LLOcclusionCullingGroup::isRecentlyVisible() const
+{
+	const S32 MIN_VIS_FRAME_RANGE = 2;
+	return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < MIN_VIS_FRAME_RANGE ;
+}
+
 //virtual 
 void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child)
 {
diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h
index 980a67367c1ff5cfda400ec40c711ec2aa27542e..7c85231ce0d573aa27497acea6378351ad7ec80c 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -317,14 +317,17 @@ class LLOcclusionCullingGroup : public LLviewerOctreeGroup
 	void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
 	void checkOcclusion(); //read back last occlusion query (if any)
 	void doOcclusion(LLCamera* camera, const LLVector3* region_agent = NULL); //issue occlusion query
-	BOOL isOcclusionState(U32 state) const	{ return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }		
-	
+	BOOL isOcclusionState(U32 state) const	{ return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
+
 	BOOL needsUpdate();
 	U32  getLastOcclusionIssuedTime();
 
 	//virtual 
 	void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
 
+	//virtual
+	BOOL isRecentlyVisible() const;
+
 	static U32 getNewOcclusionQueryObjectName();
 	static void releaseOcclusionQueryObjectName(U32 name);
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index c55ccce47af032984703308c3f2a40a3461c3f36..47e59d3c00ee1169e928e09ba5da25f4fff85da6 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1183,6 +1183,9 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
 	}
 
 	max_update_time -= update_timer.getElapsedTimeF32();	
+	
+	//reset all occluders
+	mImpl->mVOCachePartition->resetOccluders();
 
 	//update the throttling number
 	static S32 throttle = new_object_creation_throttle;
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index d1c27edce728c747ba3835a77cc39afb28348894..9beb81bcddb0918b2d53f1cb3aa9c6e7e91ee194 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -490,9 +490,8 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 
 			group->checkOcclusion();
 
-			if (group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+			if (group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
 			{
-				mPartition->addOccluders(group);
 				return true;
 			}
 		}
@@ -530,7 +529,24 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 
 	virtual void processGroup(LLviewerOctreeGroup* base_group)
 	{
-		mRegionp->addVisibleGroup(base_group);
+		LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group;
+		if(!group->isRecentlyVisible())//needs to issue new occlusion culling check.
+		{
+			mPartition->addOccluders(group);
+			group->setVisible();
+			return ; //wait for occlusion culling result
+		}
+
+		if(group->isOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING) || 
+			group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION))
+		{
+			//keep waiting
+			group->setVisible();
+		}
+		else
+		{
+			mRegionp->addVisibleGroup(base_group);
+		}
 	}
 
 private:
@@ -555,17 +571,9 @@ S32 LLVOCachePartition::cull(LLCamera &camera)
 	LLVector3 region_agent = mRegionp->getOriginAgent();
 	camera.calcRegionFrustumPlanes(region_agent);
 
-	mOccludedGroups.clear();
-	
 	LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, use_object_cache_occlusion, this);
 	culler.traverse(mOctree);
 
-	if(!mOccludedGroups.empty())
-	{
-		processOccluders(&camera, &region_agent);
-		mOccludedGroups.clear();
-	}
-
 	return 0;
 }
 
@@ -573,13 +581,6 @@ void LLVOCachePartition::addOccluders(LLviewerOctreeGroup* gp)
 {
 	LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)gp;
 
-	const U32 MIN_WAIT_TIME = 19; //wait 19 frames to issue a new occlusion request
-	U32 last_issued_time = group->getLastOcclusionIssuedTime();
-	if(!group->needsUpdate() && gFrameCount > last_issued_time && gFrameCount < last_issued_time + MIN_WAIT_TIME)
-	{
-		return;
-	}
-
 	if(!group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION))
 	{
 		group->setOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
@@ -587,14 +588,34 @@ void LLVOCachePartition::addOccluders(LLviewerOctreeGroup* gp)
 	}
 }
 
-void LLVOCachePartition::processOccluders(LLCamera* camera, const LLVector3* region_agent)
+void LLVOCachePartition::processOccluders(LLCamera* camera)
 {
+	if(mOccludedGroups.empty())
+	{
+		return;
+	}
+
+	LLVector3 region_agent = mRegionp->getOriginAgent();
 	for(std::set<LLOcclusionCullingGroup*>::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter)
 	{
 		LLOcclusionCullingGroup* group = *iter;
-		group->doOcclusion(camera, region_agent);
-		group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
+		group->doOcclusion(camera, &region_agent);
+	}	
+}
+
+void LLVOCachePartition::resetOccluders()
+{
+	if(mOccludedGroups.empty())
+	{
+		return;
 	}
+
+	for(std::set<LLOcclusionCullingGroup*>::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter)
+	{
+		LLOcclusionCullingGroup* group = *iter;
+		group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
+	}	
+	mOccludedGroups.clear();
 }
 
 //-------------------------------------------------------------------
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index 816ef88dc4207bd3054dbe272cec42093775f64e..7de8185315409da7f44b58c5ff4f47e375a8cabc 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -159,11 +159,12 @@ class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTr
 	void removeEntry(LLViewerOctreeEntry* entry);
 	/*virtual*/ S32 cull(LLCamera &camera);
 	void addOccluders(LLviewerOctreeGroup* gp);
+	void resetOccluders();
 
 	static	LLTrace::MemStatHandle	sMemStat;
 
-private:	
-	void processOccluders(LLCamera* camera, const LLVector3* region_agent);
+public:	
+	void processOccluders(LLCamera* camera);
 
 private:
 	std::set<LLOcclusionCullingGroup*> mOccludedGroups;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 1d9137c1610da904ebf8749ca710f1e77387cb9c..1696f1962c3cf336a39f120fa084525a59c12726 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2719,7 +2719,7 @@ void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderT
 
 void LLPipeline::doOcclusion(LLCamera& camera)
 {
-	if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
+	if (LLPipeline::sUseOcclusion > 1)
 	{
 		LLVertexBuffer::unbind();
 
@@ -2765,6 +2765,17 @@ void LLPipeline::doOcclusion(LLCamera& camera)
 			group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
 		}
 	
+		//apply occlusion culling to object cache tree
+		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		{
+			LLVOCachePartition* vo_part = (*iter)->getVOCachePartition();
+			if(vo_part)
+			{
+				vo_part->processOccluders(&camera);
+			}
+		}
+
 		if (bind_shader)
 		{
 			if (LLPipeline::sShadowRender)