diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2012-12-05 09:36:38 -0500 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2012-12-05 09:36:38 -0500 | 
| commit | 5a938e3a1c8582d6bfe6df2aa195afcdcafb355a (patch) | |
| tree | 2206c0edf6cfadce17d5cc294b482e5fab043a46 | |
| parent | b078a515e197473dbab34724263348dd88030b4d (diff) | |
| parent | e6712cab31df0e1d766a4d935bada18d57cd26ad (diff) | |
merge changes for DRTVWR-254
| -rwxr-xr-x | .hgtags | 1 | ||||
| -rw-r--r-- | indra/llrender/llrendertarget.cpp | 34 | ||||
| -rw-r--r-- | indra/llrender/llrendertarget.h | 5 | ||||
| -rwxr-xr-x | indra/newview/app_settings/settings.xml | 12 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl | 1 | ||||
| -rwxr-xr-x | indra/newview/llfloaterpreference.cpp | 5 | ||||
| -rwxr-xr-x | indra/newview/llviewerwindow.cpp | 55 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 80 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 19 | 
9 files changed, 159 insertions, 53 deletions
@@ -365,3 +365,4 @@ f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232  965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252  bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251  ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253 +48382ec79741671d19ce4cc3e8cd59e9a521e4a7 DRTVWR-254 diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 846311a8d0..c1b96a43da 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -51,11 +51,13 @@ void check_framebuffer_status()  }  bool LLRenderTarget::sUseFBO = false; +U32 LLRenderTarget::sCurFBO = 0;  LLRenderTarget::LLRenderTarget() :  	mResX(0),  	mResY(0),  	mFBO(0), +	mPreviousFBO(0),  	mDepth(0),  	mStencil(0),  	mUseDepth(false), @@ -107,6 +109,9 @@ void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt)  bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)  { +	resx = llmin(resx, (U32) 4096); +	resy = llmin(resy, (U32) 4096); +  	stop_glerror();  	release();  	stop_glerror(); @@ -146,7 +151,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo  				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);  				stop_glerror();  			} -			glBindFramebuffer(GL_FRAMEBUFFER, 0); +			glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);  		}  		stop_glerror(); @@ -233,7 +238,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)  		check_framebuffer_status(); -		glBindFramebuffer(GL_FRAMEBUFFER, 0); +		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);  	}  	mTex.push_back(tex); @@ -322,7 +327,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)  		check_framebuffer_status(); -		glBindFramebuffer(GL_FRAMEBUFFER, 0); +		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);  		target.mUseDepth = true;  	} @@ -385,9 +390,13 @@ void LLRenderTarget::bindTarget()  {  	if (mFBO)  	{ +		mPreviousFBO = sCurFBO; +  		stop_glerror();  		glBindFramebuffer(GL_FRAMEBUFFER, mFBO); +		sCurFBO = mFBO; +  		stop_glerror();  		if (gGLManager.mHasDrawBuffers)  		{ //setup multiple render targets @@ -413,16 +422,6 @@ void LLRenderTarget::bindTarget()  	sBoundTarget = this;  } -// static -void LLRenderTarget::unbindTarget() -{ -	if (gGLManager.mHasFramebufferObject) -	{ -		glBindFramebuffer(GL_FRAMEBUFFER, 0); -	} -	sBoundTarget = NULL; -} -  void LLRenderTarget::clear(U32 mask_in)  {  	U32 mask = GL_COLOR_BUFFER_BIT; @@ -488,7 +487,8 @@ void LLRenderTarget::flush(bool fetch_depth)  	else  	{  		stop_glerror(); -		glBindFramebuffer(GL_FRAMEBUFFER, 0); +		glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO); +		sCurFBO = mPreviousFBO;  		stop_glerror();  	}  } @@ -518,7 +518,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,  		stop_glerror();  		glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);  		stop_glerror(); -		glBindFramebuffer(GL_FRAMEBUFFER, 0); +		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);  		stop_glerror();  	}  	else @@ -535,7 +535,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,  		stop_glerror();  		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);  		stop_glerror(); -		glBindFramebuffer(GL_FRAMEBUFFER, 0); +		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);  		stop_glerror();  	}  } @@ -561,7 +561,7 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0  		stop_glerror();  		glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);  		stop_glerror(); -		glBindFramebuffer(GL_FRAMEBUFFER, 0); +		glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);  		stop_glerror();  	}  } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index e1a51304f1..cf15f66d31 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -63,6 +63,7 @@ public:  	//whether or not to use FBO implementation  	static bool sUseFBO;   	static U32 sBytesAllocated; +	static U32 sCurFBO;  	LLRenderTarget();  	~LLRenderTarget(); @@ -96,9 +97,6 @@ public:  	//applies appropriate viewport  	void bindTarget(); -	//unbind target for rendering -	static void unbindTarget(); -	  	//clear render targer, clears depth buffer if present,  	//uses scissor rect if in copy-to-texture mode  	void clear(U32 mask = 0xFFFFFFFF); @@ -148,6 +146,7 @@ protected:  	std::vector<U32> mTex;  	std::vector<U32> mInternalFormat;  	U32 mFBO; +	U32 mPreviousFBO;  	U32 mDepth;  	bool mStencil;  	bool mUseDepth; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4fa1663907..7801edb155 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14070,5 +14070,17 @@          <real>1.0</real>        </array>      </map> + +  <key>SimulateFBOFailure</key> +  <map> +    <key>Comment</key> +    <string>[DEBUG] Make allocateScreenBuffer return false.  Used to test error handling.</string> +    <key>Persist</key> +    <integer>0</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map>  </map>  </llsd> diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index e02a7b405b..2cef8f2a5d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -2093,7 +2093,6 @@ uniform sampler2D diffuseMap;  uniform vec2 rcp_screen_res;  uniform vec4 rcp_frame_opt;  uniform vec4 rcp_frame_opt2; -uniform vec2 screen_res;  VARYING vec2 vary_fragcoord;  VARYING vec2 vary_tc; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5752f839ce..542e96cf16 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -750,7 +750,10 @@ void LLFloaterPreference::onClose(bool app_quitting)  {  	gSavedSettings.setS32("LastPrefTab", getChild<LLTabContainer>("pref core")->getCurrentPanelIndex());  	LLPanelLogin::setAlwaysRefresh(false); -	cancel(); +	if (!app_quitting) +	{ +		cancel(); +	}  }  void LLFloaterPreference::onOpenHardwareSettings() diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 44e6d70546..ffaf881521 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4236,14 +4236,48 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei  		image_height = llmin(image_height, window_height);  	} +	S32 original_width = 0; +	S32 original_height = 0; +	bool reset_deferred = false; + +	LLRenderTarget scratch_space; +  	F32 scale_factor = 1.0f ;  	if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height))  	{	 -		// if image cropping or need to enlarge the scene, compute a scale_factor -		F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; -		snapshot_width  = (S32)(ratio * image_width) ; -		snapshot_height = (S32)(ratio * image_height) ; -		scale_factor = llmax(1.0f, 1.0f / ratio) ; +		if ((image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) +		{ +			if (scratch_space.allocate(image_width, image_height, GL_RGBA, true, true)) +			{ +				original_width = gPipeline.mDeferredScreen.getWidth(); +				original_height = gPipeline.mDeferredScreen.getHeight(); + +				if (gPipeline.allocateScreenBuffer(image_width, image_height)) +				{ +					window_width = image_width; +					window_height = image_height; +					snapshot_width = image_width; +					snapshot_height = image_height; +					reset_deferred = true; +					mWorldViewRectRaw.set(0, image_height, image_width, 0); +					scratch_space.bindTarget(); +				} +				else +				{ +					scratch_space.release(); +					gPipeline.allocateScreenBuffer(original_width, original_height); +				} +			} +		} + +		if (!reset_deferred) +		{ +			// if image cropping or need to enlarge the scene, compute a scale_factor +			F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; +			snapshot_width  = (S32)(ratio * image_width) ; +			snapshot_height = (S32)(ratio * image_height) ; +			scale_factor = llmax(1.0f, 1.0f / ratio) ; +		}  	}  	if (show_ui && scale_factor > 1.f) @@ -4432,11 +4466,20 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei  		gPipeline.resetDrawOrders();  	} +	if (reset_deferred) +	{ +		mWorldViewRectRaw = window_rect; +		scratch_space.flush(); +		scratch_space.release(); +		gPipeline.allocateScreenBuffer(original_width, original_height); +		 +	} +  	if (high_res)  	{  		send_agent_resume();  	} - +	  	return ret;  } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ea2dc60b07..ab45bd3d3b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -779,18 +779,57 @@ void LLPipeline::allocatePhysicsBuffer()  	}  } -void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) +bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)  {  	refreshCachedSettings(); -	U32 samples = RenderFSAASamples; +	 +	bool save_settings = sRenderDeferred; +	if (save_settings) +	{ +		// Set this flag in case we crash while resizing window or allocating space for deferred rendering targets +		gSavedSettings.setBOOL("RenderInitError", TRUE); +		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); +	} + +	eFBOStatus ret = doAllocateScreenBuffer(resX, resY); + +	if (save_settings) +	{ +		// don't disable shaders on next session +		gSavedSettings.setBOOL("RenderInitError", FALSE); +		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); +	} +	 +	if (ret == FBO_FAILURE) +	{ //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled +		//NOTE: if the session closes successfully after this call, deferred rendering will be  +		// disabled on future sessions +		if (LLPipeline::sRenderDeferred) +		{ +			gSavedSettings.setBOOL("RenderDeferred", FALSE); +			LLPipeline::refreshCachedSettings(); +		} +	} + +	return ret == FBO_SUCCESS_FULLRES; +} -	//try to allocate screen buffers at requested resolution and samples + +LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) +{ +	// try to allocate screen buffers at requested resolution and samples  	// - on failure, shrink number of samples and try again  	// - if not multisampled, shrink resolution and try again (favor X resolution over Y)  	// Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state +	U32 samples = RenderFSAASamples; + +	eFBOStatus ret = FBO_SUCCESS_FULLRES;  	if (!allocateScreenBuffer(resX, resY, samples))  	{ +		//failed to allocate at requested specification, return false +		ret = FBO_FAILURE; +  		releaseScreenBuffers();  		//reduce number of samples   		while (samples > 0) @@ -798,7 +837,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)  			samples /= 2;  			if (allocateScreenBuffer(resX, resY, samples))  			{ //success -				return; +				return FBO_SUCCESS_LOWRES;  			}  			releaseScreenBuffers();  		} @@ -811,22 +850,23 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)  			resY /= 2;  			if (allocateScreenBuffer(resX, resY, samples))  			{ -				return; +				return FBO_SUCCESS_LOWRES;  			}  			releaseScreenBuffers();  			resX /= 2;  			if (allocateScreenBuffer(resX, resY, samples))  			{ -				return; +				return FBO_SUCCESS_LOWRES;  			}  			releaseScreenBuffers();  		}  		llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;  	} -} +	return ret; +}  bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  { @@ -854,10 +894,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  	if (LLPipeline::sRenderDeferred)  	{ -		// Set this flag in case we crash while resizing window or allocating space for deferred rendering targets -		gSavedSettings.setBOOL("RenderInitError", TRUE); -		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); -  		S32 shadow_detail = RenderShadowDetail;  		BOOL ssao = RenderDeferredSSAO; @@ -869,7 +905,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  		if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;  		if (samples > 0)  		{ -			if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; +			if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;  		}  		else  		{ @@ -903,7 +939,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  			}  		} -		U32 width = nhpo2(U32(resX*scale))/2; +		U32 width = (U32) (resX*scale);  		U32 height = width;  		if (shadow_detail > 1) @@ -922,9 +958,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)  			}  		} -		// don't disable shaders on next session -		gSavedSettings.setBOOL("RenderInitError", FALSE); -		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); +		//HACK make screenbuffer allocations start failing after 30 seconds +		if (gSavedSettings.getBOOL("SimulateFBOFailure")) +		{ +			return false; +		}  	}  	else  	{ @@ -7117,11 +7155,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)  	gGlowProgram.unbind(); -	if (LLRenderTarget::sUseFBO) +	/*if (LLRenderTarget::sUseFBO)  	{  		LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);  		glBindFramebuffer(GL_FRAMEBUFFER, 0); -	} +	}*/  	gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;  	gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; @@ -7997,10 +8035,6 @@ void LLPipeline::renderDeferredLighting()  		gGL.popMatrix();  		stop_glerror(); -		//copy depth and stencil from deferred screen -		//mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), -		//					0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); -  		mScreen.bindTarget();  		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky  		glClearColor(0,0,0,0); @@ -8772,8 +8806,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)  		}  		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; -		LLRenderTarget::unbindTarget(); -  		LLPipeline::sReflectionRender = FALSE;  		if (!LLRenderTarget::sUseFBO) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 7a0ca86231..36abeca295 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -119,8 +119,25 @@ public:  	void createGLBuffers();  	void createLUTBuffers(); -	void allocateScreenBuffer(U32 resX, U32 resY); +	//allocate the largest screen buffer possible up to resX, resY +	//returns true if full size buffer allocated, false if some other size is allocated +	bool allocateScreenBuffer(U32 resX, U32 resY); + +	typedef enum { +		FBO_SUCCESS_FULLRES = 0, +		FBO_SUCCESS_LOWRES, +		FBO_FAILURE +	} eFBOStatus; + +private: +	//implementation of above, wrapped for easy error handling +	eFBOStatus doAllocateScreenBuffer(U32 resX, U32 resY); +public: + +	//attempt to allocate screen buffers at resX, resY +	//returns true if allocation successful, false otherwise  	bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); +  	void allocatePhysicsBuffer();  	void resetVertexBuffers(LLDrawable* drawable);  | 
