Commits

davep committed 49ed482

MAINT-616 Faster issuance of occlusion queries.

Comments (0)

Files changed (11)

indra/llrender/llshadermgr.cpp

 	mReservedUniforms.push_back("size");
 	mReservedUniforms.push_back("falloff");
 
+	mReservedUniforms.push_back("box_center");
+	mReservedUniforms.push_back("box_size");
+
 
 	mReservedUniforms.push_back("minLuminance");
 	mReservedUniforms.push_back("maxExtractAlpha");

indra/llrender/llshadermgr.h

 		LIGHT_CENTER,
 		LIGHT_SIZE,
 		LIGHT_FALLOFF,
+		BOX_CENTER,
+		BOX_SIZE,
 
 		GLOW_MIN_LUMINANCE,
 		GLOW_MAX_EXTRACT_ALPHA,

indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl

+/** 
+ * @file shadowCubeV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&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;
+
+VARYING vec4 post_pos;
+
+uniform vec3 box_center;
+uniform vec3 box_size;
+
+void main()
+{
+	//transform vertex
+	vec3 p = position*box_size+box_center;
+	vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
+	
+	post_pos = pos;
+	
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+}

indra/newview/app_settings/shaders/class1/interface/occlusionCubeV.glsl

+/** 
+ * @file occlusionCubeV.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;
+
+uniform vec3 box_center;
+uniform vec3 box_size;
+
+void main()
+{
+	vec3 p = position*box_size+box_center;
+	gl_Position = modelview_projection_matrix * vec4(p.xyz, 1.0);
+}
+

indra/newview/llspatialpartition.cpp

 
 static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion");
 
-void LLSpatialGroup::buildOcclusion()
-{
-	//if (mOcclusionVerts.isNull())
-	{
-		mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 
-			LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling.
-		mOcclusionVerts->allocateBuffer(8, 64, true);
-	
-		LLStrider<U16> idx;
-		mOcclusionVerts->getIndexStrider(idx);
-		for (U32 i = 0; i < 64; i++)
-		{
-			*idx++ = sOcclusionIndices[i];
-		}
-	}
-
-	LLVector4a fudge;
-	fudge.splat(SG_OCCLUSION_FUDGE);
-
-	LLVector4a r;
-	r.setAdd(mBounds[1], fudge);
-
-	LLStrider<LLVector3> pos;
-	
-	{
-		LLFastTimer t(FTM_BUILD_OCCLUSION);
-		mOcclusionVerts->getVertexStrider(pos);
-	}
-
-	{
-		LLVector4a* v = (LLVector4a*) pos.get();
-
-		const LLVector4a& c = mBounds[0];
-		const LLVector4a& s = r;
-		
-		static const LLVector4a octant[] =
-		{
-			LLVector4a(-1.f, -1.f, -1.f),
-			LLVector4a(-1.f, -1.f, 1.f),
-			LLVector4a(-1.f, 1.f, -1.f),
-			LLVector4a(-1.f, 1.f, 1.f),
-
-			LLVector4a(1.f, -1.f, -1.f),
-			LLVector4a(1.f, -1.f, 1.f),
-			LLVector4a(1.f, 1.f, -1.f),
-			LLVector4a(1.f, 1.f, 1.f),
-		};
-
-		//vertex positions are encoded so the 3 bits of their vertex index 
-		//correspond to their axis facing, with bit position 3,2,1 matching
-		//axis facing x,y,z, bit set meaning positive facing, bit clear 
-		//meaning negative facing
-		
-		for (S32 i = 0; i < 8; ++i)
-		{
-			LLVector4a p;
-			p.setMul(s, octant[i]);
-			p.add(c);
-			v[i] = p;
-		}
-	}
-	
-	{
-		mOcclusionVerts->flush();
-		LLVertexBuffer::unbind();
-	}
-
-	clearState(LLSpatialGroup::OCCLUSION_DIRTY);
-}
-
-
 BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
 
 //returns:
 		}
 	}
 
-	mOcclusionVerts = NULL;
-
 	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
 	clearDrawMap();
 	clearAtlasList() ;
 		setState(GEOM_DIRTY);
 		gPipeline.markRebuild(this, TRUE);
 	}
-
-	if (mOcclusionVerts.notNull())
-	{
-		setState(OCCLUSION_DIRTY);
-	}
 }
 
 class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
 		mVisible[i] = 0;
 	}
 
-	mOcclusionVerts = NULL;
-
 	mRadius = 1;
 	mPixelArea = 1024.f;
 }
 				mOcclusionQuery[i] = 0;
 			}
 		}
-
-		mOcclusionVerts = NULL;
 	}
 
 
 		mBounds[1].mul(0.5f);
 	}
 	
-	setState(OCCLUSION_DIRTY);
-	
 	clearState(DIRTY);
 
 	return TRUE;
 						mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
 					}
 
-					if (mOcclusionVerts.isNull() || isState(LLSpatialGroup::OCCLUSION_DIRTY))
-					{
-						LLFastTimer t(FTM_OCCLUSION_BUILD);
-						buildOcclusion();
-					}
-					
 					// 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.
 							glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);					
 						}
 					
-						{
-							LLFastTimer t(FTM_OCCLUSION_SET_BUFFER);
-							mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
-						}
+						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)
 						{
 							LLGLSquashToFarClip squash(glh_get_current_projection(), 1);
 							if (camera->getOrigin().isExactlyZero())
 							{ //origin is invalid, draw entire box
-								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
-								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				
+								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
+								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				
 							}
 							else
 							{
-								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
+								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
-								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
-								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				
+								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
+								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);				
 							}
 							else
 							{
-								mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
+								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
 							}
 						}
 
 			gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f);
 			pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
 		}
-		/*else if (camera && group->mOcclusionVerts.notNull())
-		{
-			LLVertexBuffer::unbind();
-			group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			
-			gGL.diffuseColor4f(1.0f, 0.f, 0.f, 0.5f);
-			group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0]));
-			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-			
-			gGL.diffuseColor4f(1.0f, 1.f, 1.f, 1.0f);
-			group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0]));
-			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-		}*/
 	}
 }
 

indra/newview/llspatialpartition.h

 		SKIP_FRUSTUM_CHECK		= 0x00000020,
 		IN_IMAGE_QUEUE			= 0x00000040,
 		IMAGE_DIRTY				= 0x00000080,
-		OCCLUSION_DIRTY			= 0x00000100,
-		MESH_DIRTY				= 0x00000200,
-		NEW_DRAWINFO			= 0x00000400,
-		IN_BUILD_Q1				= 0x00000800,
-		IN_BUILD_Q2				= 0x00001000,
+		MESH_DIRTY				= 0x00000100,
+		NEW_DRAWINFO			= 0x00000200,
+		IN_BUILD_Q1				= 0x00000400,
+		IN_BUILD_Q2				= 0x00000800,
 		STATE_MASK				= 0x0000FFFF,
 	} eSpatialState;
 
 	BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax);
 	void unbound();
 	BOOL rebound();
-	void buildOcclusion(); //rebuild mOcclusionVerts
 	void checkOcclusion(); //read back last occlusion query (if any)
 	void doOcclusion(LLCamera* camera); //issue occlusion query
 	void destroyGL(bool keep_occlusion = false);
 	LLSpatialPartition* mSpatialPartition;
 	
 	LLPointer<LLVertexBuffer> mVertexBuffer;
-	LLPointer<LLVertexBuffer> mOcclusionVerts;
 	GLuint					mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
 
 	U32 mBufferUsage;

indra/newview/llviewercontrol.cpp

 
 static bool handleUseOcclusionChanged(const LLSD& newvalue)
 {
-	LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery 
+	LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery && LLGLSLShader::sNoFixedFunction
 		&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0;
 	return true;
 }

indra/newview/llviewerdisplay.cpp

 		LLSpatialGroup::sNoDelete = TRUE;
 		LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
 
-		/*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
-		{ //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
-			LLPipeline::sUseOcclusion = 3;
-		}*/
-
 		S32 occlusion = LLPipeline::sUseOcclusion;
 		if (gDepthDirty)
 		{ //depth buffer is invalid, don't overwrite occlusion state

indra/newview/llviewershadermgr.cpp

 
 //utility shaders
 LLGLSLShader	gOcclusionProgram;
+LLGLSLShader	gOcclusionCubeProgram;
 LLGLSLShader	gCustomAlphaProgram;
 LLGLSLShader	gGlowCombineProgram;
 LLGLSLShader	gSplatTextureRectProgram;
 LLGLSLShader			gDeferredBlurLightProgram;
 LLGLSLShader			gDeferredSoftenProgram;
 LLGLSLShader			gDeferredShadowProgram;
+LLGLSLShader			gDeferredShadowCubeProgram;
 LLGLSLShader			gDeferredShadowAlphaMaskProgram;
 LLGLSLShader			gDeferredAvatarShadowProgram;
 LLGLSLShader			gDeferredAttachmentShadowProgram;
 void LLViewerShaderMgr::unloadShaders()
 {
 	gOcclusionProgram.unload();
+	gOcclusionCubeProgram.unload();
 	gDebugProgram.unload();
 	gClipProgram.unload();
 	gAlphaMaskProgram.unload();
 		gDeferredBlurLightProgram.unload();
 		gDeferredSoftenProgram.unload();
 		gDeferredShadowProgram.unload();
+		gDeferredShadowCubeProgram.unload();
 		gDeferredShadowAlphaMaskProgram.unload();
 		gDeferredAvatarShadowProgram.unload();
 		gDeferredAttachmentShadowProgram.unload();
 
 	if (success)
 	{
+		gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader";
+		gDeferredShadowCubeProgram.mShaderFiles.clear();
+		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredShadowCubeProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
 		gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader";
 		gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.clear();
 
 	if (success)
 	{
+		gOcclusionCubeProgram.mName = "Occlusion Cube Shader";
+		gOcclusionCubeProgram.mShaderFiles.clear();
+		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB));
+		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		success = gOcclusionCubeProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
 		gDebugProgram.mName = "Debug Shader";
 		gDebugProgram.mShaderFiles.clear();
 		gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB));

indra/newview/llviewershadermgr.h

 
 //utility shaders
 extern LLGLSLShader			gOcclusionProgram;
+extern LLGLSLShader			gOcclusionCubeProgram;
 extern LLGLSLShader			gCustomAlphaProgram;
 extern LLGLSLShader			gGlowCombineProgram;
 extern LLGLSLShader			gSplatTextureRectProgram;
 extern LLGLSLShader			gDeferredAvatarProgram;
 extern LLGLSLShader			gDeferredSoftenProgram;
 extern LLGLSLShader			gDeferredShadowProgram;
+extern LLGLSLShader			gDeferredShadowCubeProgram;
 extern LLGLSLShader			gDeferredShadowAlphaMaskProgram;
 extern LLGLSLShader			gDeferredPostProgram;
 extern LLGLSLShader			gDeferredCoFProgram;

indra/newview/pipeline.cpp

 
 	LLPipeline::sUseOcclusion = 
 			(!gUseWireframe
+			&& LLGLSLShader::sNoFixedFunction
 			&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") 
 			&& gSavedSettings.getBOOL("UseOcclusion") 
 			&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
 	gGLLastMatrix = NULL;
 	gGL.loadMatrix(gGLLastModelView);
 
-
-	LLVertexBuffer::unbind();
 	LLGLDisable blend(GL_BLEND);
 	LLGLDisable test(GL_ALPHA_TEST);
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	{ //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
 		// (shadow render uses a special shader that clamps to clip planes)
 		bound_shader = true;
-		gOcclusionProgram.bind();
+		gOcclusionCubeProgram.bind();
+	}
+
+	if (sUseOcclusion > 1)
+	{
+		if (mCubeVB.isNull())
+		{ //cube VB will be used for issuing occlusion queries
+			mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+		}
+		mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 	}
 	
 	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
 
 	if (bound_shader)
 	{
-		gOcclusionProgram.unbind();
+		gOcclusionCubeProgram.unbind();
 	}
 
 	camera.disableUserClipPlane();
 		{
 			if (LLPipeline::sShadowRender)
 			{
-				gDeferredShadowProgram.bind();
+				gDeferredShadowCubeProgram.bind();
 			}
 			else
 			{
-				gOcclusionProgram.bind();
-			}
-		}
+				gOcclusionCubeProgram.bind();
+			}
+		}
+
+		if (mCubeVB.isNull())
+		{ //cube VB will be used for issuing occlusion queries
+			mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+		}
+		mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 
 		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
 		{
 		{
 			if (LLPipeline::sShadowRender)
 			{
-				gDeferredShadowProgram.unbind();
+				gDeferredShadowCubeProgram.unbind();
 			}
 			else
 			{
-				gOcclusionProgram.unbind();
+				gOcclusionCubeProgram.unbind();
 			}
 		}
 
 
 	if (use_shader)
 	{
-		gDeferredShadowProgram.bind();
+		gDeferredShadowCubeProgram.bind();
 	}
 
 	updateCull(shadow_cam, result);
 	stop_glerror();
 	gGLLastMatrix = NULL;
 
-	{
-		//LLGLDepthTest depth(GL_TRUE);
-		//glClear(GL_DEPTH_BUFFER_BIT);
-	}
-
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	
 	stop_glerror();
 	
-	//glCullFace(GL_FRONT);
-
 	LLVertexBuffer::unbind();
 
 	{
 		{ //occlusion program is general purpose depth-only no-textures
 			gOcclusionProgram.bind();
 		}
+		else
+		{
+			gDeferredShadowProgram.bind();
+		}
 
 		gGL.diffuseColor4f(1,1,1,1);
 		gGL.setColorMask(false, false);
 
 	//glCullFace(GL_BACK);
 
-	gDeferredShadowProgram.bind();
+	gDeferredShadowCubeProgram.bind();
 	gGLLastMatrix = NULL;
 	gGL.loadMatrix(gGLModelView);
 	doOcclusion(shadow_cam);