merge changes for DRTVWR-254

meow-7.2.2
Nat Goodspeed 2012-12-05 09:36:38 -05:00
commit 5a938e3a1c
9 changed files with 159 additions and 53 deletions

View File

@ -365,3 +365,4 @@ f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232
965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252
bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251
ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
48382ec79741671d19ce4cc3e8cd59e9a521e4a7 DRTVWR-254

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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;

View File

@ -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()

View File

@ -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;
}

View File

@ -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 );
}
//try to allocate screen buffers at requested resolution and samples
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;
}
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)

View File

@ -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);