virtual void visit(const OctreeNode* branch) { LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*) branch->getListener(0); if(group) { group->clearOcclusionState(mState); } }
virtual void traverse(const OctreeNode* n) { LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*) n->getListener(0); if (group && group->isOcclusionState(mState)) { OctreeTraveler::traverse(n); } }
virtual bool earlyFail(LLViewerOctreeGroup* base_group) { if( mUseObjectCacheOcclusion && base_group->getOctreeNode()->getParent()) //never occlusion cull the root node { LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; if (group->getOcclusionState() > 0) //occlusion state is not clear. { return true; } } return false; }
virtual void processGroup(LLViewerOctreeGroup* base_group) { if( !mUseObjectCacheOcclusion || !base_group->getOctreeNode()->getParent()) { //no occlusion check if(mRegionp->addVisibleGroup(base_group)) { base_group->setVisible(); } return; } LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; if(group->needsUpdate() || !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 { if(mRegionp->addVisibleGroup(base_group)) { base_group->setVisible(); } } }
virtual bool earlyFail(LLViewerOctreeGroup* base_group) { if( mUseObjectCacheOcclusion && base_group->getOctreeNode()->getParent()) //never occlusion cull the root node { LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; if(group->needsUpdate()) { //needs to issue new occlusion culling check, perform view culling check first. return false; } group->checkOcclusion(); if (group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) { return true; } } return false; }
bool LLVOCacheEntry::isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold) { LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)getGroup(); if(!group) { return false; } //any visible bool vis = group->isAnyRecentlyVisible(); //not ready to remove if(!vis) { S32 cur_vis = llmax(group->getAnyVisible(), (S32)getVisible()); vis = (cur_vis + sMinFrameRange > LLViewerOctreeEntryData::getCurrentFrame()); } //within the back sphere if(!vis && !mParentID && !group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) { LLVector4a lookAt; if(mBSphereRadius > 0.f) { lookAt.setSub(mBSphereCenter, local_camera_origin); dist_threshold += mBSphereRadius; } else { lookAt.setSub(getPositionGroup(), camera_origin); dist_threshold += getBinRadius(); } vis = (lookAt.dot3(lookAt).getF32() < dist_threshold * dist_threshold); } return vis; }
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("RenderSynchronousOcclusion", true); 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*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 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); } } }