diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index d631985e8207b53d3b94d415596be01c36d27f1d..576dbfd2c2f1836fadcf374b1b571373550258ce 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -1022,6 +1022,11 @@ BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera)
 	return TRUE;
 }
 
+U32 LLOcclusionCullingGroup::getLastOcclusionIssuedTime()
+{
+	return mOcclusionIssued[LLViewerCamera::sCurCameraID];
+}
+
 void LLOcclusionCullingGroup::checkOcclusion()
 {
 	if (LLPipeline::sUseOcclusion > 1)
diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h
index 7f2ca6ed2d47d610ec71fa68dd4c304fa47c3a41..e210d8f47833147d9877afe155904e136bbf5cd0 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -320,6 +320,7 @@ class LLOcclusionCullingGroup : public LLviewerOctreeGroup
 	BOOL isOcclusionState(U32 state) const	{ return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }		
 	
 	BOOL needsUpdate();
+	U32  getLastOcclusionIssuedTime();
 
 	//virtual 
 	void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index b3c7b80c29e42775ba113c9d549b1258c3441fb9..f23375adfa4f114875d753891b94b66fdf2d3083 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -399,9 +399,10 @@ void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry)
 class LLVOCacheOctreeCull : public LLViewerOctreeCull
 {
 public:
-	LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, const LLVector3& shift, bool use_object_cache_occlusion) 
+	LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, const LLVector3& shift, bool use_object_cache_occlusion, LLVOCachePartition* part) 
 		: LLViewerOctreeCull(camera), 
-		  mRegionp(regionp)
+		  mRegionp(regionp),
+		  mPartition(part)
 	{
 		mLocalShift = shift;
 		mUseObjectCacheOcclusion = (use_object_cache_occlusion && LLPipeline::sUseOcclusion);
@@ -422,6 +423,7 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 
 			if (group->isOcclusionState(LLSpatialGroup::OCCLUDED))
 			{
+				mPartition->addOccluders(group);
 				return true;
 			}
 		}
@@ -473,9 +475,10 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 	}
 
 private:
-	LLViewerRegion* mRegionp;
-	LLVector3       mLocalShift; //shift vector from agent space to local region space.
-	bool            mUseObjectCacheOcclusion;
+	LLVOCachePartition* mPartition;
+	LLViewerRegion*     mRegionp;
+	LLVector3           mLocalShift; //shift vector from agent space to local region space.
+	bool                mUseObjectCacheOcclusion;
 };
 
 S32 LLVOCachePartition::cull(LLCamera &camera)
@@ -493,12 +496,48 @@ S32 LLVOCachePartition::cull(LLCamera &camera)
 	LLVector3 region_agent = mRegionp->getOriginAgent();
 	camera.calcRegionFrustumPlanes(region_agent);
 
-	LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, use_object_cache_occlusion);
+	mOccludedGroups.clear();
+	
+	LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, use_object_cache_occlusion, this);
 	culler.traverse(mOctree);
 
+	if(!mOccludedGroups.empty())
+	{
+		processOccluders(&camera);
+		mOccludedGroups.clear();
+	}
+
 	return 0;
 }
 
+void LLVOCachePartition::addOccluders(LLviewerOctreeGroup* gp)
+{
+	LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)gp;
+
+	const U32 MIN_WAIT_TIME = 16; //wait 16 frames to issue a new occlusion request
+	U32 last_issued_time = group->getLastOcclusionIssuedTime();
+	if(gFrameCount > last_issued_time && gFrameCount < last_issued_time + MIN_WAIT_TIME)
+	{
+		return;
+	}
+
+	if(group && !group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION))
+	{
+		group->setOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
+		mOccludedGroups.insert(group);
+	}
+}
+
+void LLVOCachePartition::processOccluders(LLCamera* camera)
+{
+	for(std::set<LLOcclusionCullingGroup*>::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter)
+	{
+		LLOcclusionCullingGroup* group = *iter;
+		group->doOcclusion(camera);
+		group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION);
+	}
+}
+
 //-------------------------------------------------------------------
 //LLVOCache
 //-------------------------------------------------------------------
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index b8a7ccac99fb5ea69bff1e13b4bf7205c00fe209..1aa58528db01b41ddcd053adc698b4ad353c9af4 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -156,8 +156,15 @@ class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTr
 	void addEntry(LLViewerOctreeEntry* entry);
 	void removeEntry(LLViewerOctreeEntry* entry);
 	/*virtual*/ S32 cull(LLCamera &camera);
+	void addOccluders(LLviewerOctreeGroup* gp);
 
 	static	LLTrace::MemStatHandle	sMemStat;
+
+private:	
+	void processOccluders(LLCamera* camera);
+
+private:
+	std::set<LLOcclusionCullingGroup*> mOccludedGroups;
 };
 
 //