summaryrefslogtreecommitdiff
path: root/indra/newview/pipeline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/pipeline.cpp')
-rw-r--r--indra/newview/pipeline.cpp180
1 files changed, 113 insertions, 67 deletions
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c523a78b22..ed636a40b2 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -187,6 +187,7 @@ F32 LLPipeline::RenderShadowFOVCutoff;
BOOL LLPipeline::CameraOffset;
F32 LLPipeline::CameraMaxCoF;
F32 LLPipeline::CameraDoFResScale;
+F32 LLPipeline::RenderAutoHideSurfaceAreaLimit;
const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
@@ -203,10 +204,6 @@ extern S32 gBoxFrame;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDebugGL;
-// hack counter for rendering a fixed number of frames after toggling
-// fullscreen to work around DEV-5361
-static S32 sDelayedVBOEnable = 0;
-
BOOL gAvatarBacklight = FALSE;
BOOL gDebugPipeline = FALSE;
@@ -411,6 +408,7 @@ LLPipeline::LLPipeline() :
mOldRenderDebugMask(0),
mGroupQ1Locked(false),
mGroupQ2Locked(false),
+ mResetVertexBuffers(false),
mLastRebuildPool(NULL),
mAlphaPool(NULL),
mSkyPool(NULL),
@@ -595,6 +593,7 @@ void LLPipeline::init()
gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
}
LLPipeline::~LLPipeline()
@@ -692,8 +691,6 @@ void LLPipeline::destroyGL()
if (LLVertexBuffer::sEnableVBOs)
{
- // render 30 frames after switching to work around DEV-5361
- sDelayedVBOEnable = 30;
LLVertexBuffer::sEnableVBOs = FALSE;
}
}
@@ -816,6 +813,10 @@ 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;
@@ -847,9 +848,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (shadow_detail > 0)
{ //allocate 4 sun shadow maps
+ U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur
for (U32 i = 0; i < 4; i++)
{
- if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
+ if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
}
}
else
@@ -865,9 +867,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (shadow_detail > 1)
{ //allocate two spot shadow maps
+ U32 spot_shadow_map_width = width;
for (U32 i = 4; i < 6; i++)
{
- if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false;
+ if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false;
}
}
else
@@ -877,6 +880,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
mShadow[i].release();
}
}
+
+ // don't disable shaders on next session
+ gSavedSettings.setBOOL("RenderInitError", FALSE);
+ gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
}
else
{
@@ -1012,6 +1019,7 @@ void LLPipeline::refreshCachedSettings()
CameraOffset = gSavedSettings.getBOOL("CameraOffset");
CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
+ RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit");
updateRenderDeferred();
}
@@ -1032,11 +1040,7 @@ void LLPipeline::releaseGLBuffers()
mTrueNoiseMap = 0;
}
- if (mLightFunc)
- {
- LLImageGL::deleteTextures(1, &mLightFunc);
- mLightFunc = 0;
- }
+ releaseLUTBuffers();
mWaterRef.release();
mWaterDis.release();
@@ -1052,6 +1056,15 @@ void LLPipeline::releaseGLBuffers()
LLVOAvatar::resetImpostors();
}
+void LLPipeline::releaseLUTBuffers()
+{
+ if (mLightFunc)
+ {
+ LLImageGL::deleteTextures(1, &mLightFunc);
+ mLightFunc = 0;
+ }
+}
+
void LLPipeline::releaseScreenBuffers()
{
mUIScreen.release();
@@ -1081,10 +1094,11 @@ void LLPipeline::createGLBuffers()
if (LLPipeline::sWaterReflections)
{ //water reflection texture
- U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
+ U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512);
mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
- mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
+ //always use FBO for mWaterDis so it can be used for avatar texture bakes
+ mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true);
}
mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
@@ -1127,7 +1141,7 @@ void LLPipeline::createGLBuffers()
LLImageGL::generateTextures(1, &mNoiseMap);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
@@ -1142,54 +1156,73 @@ void LLPipeline::createGLBuffers()
LLImageGL::generateTextures(1, &mTrueNoiseMap);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+ createLUTBuffers();
+ }
+
+ gBumpImageList.restoreGL();
+}
+
+void LLPipeline::createLUTBuffers()
+{
+ if (sRenderDeferred)
+ {
if (!mLightFunc)
{
U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
- U8* lg = new U8[lightResX*lightResY];
-
+ U8* ls = new U8[lightResX*lightResY];
+ F32 specExp = gSavedSettings.getF32("RenderSpecularExponent");
+ // Calculate the (normalized) Blinn-Phong specular lookup texture.
for (U32 y = 0; y < lightResY; ++y)
{
for (U32 x = 0; x < lightResX; ++x)
{
- //spec func
+ ls[y*lightResX+x] = 0;
F32 sa = (F32) x/(lightResX-1);
F32 spec = (F32) y/(lightResY-1);
- //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
-
- //F32 sp = acosf(sa)/(1.f-spec);
-
- sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
- F32 a = acosf(sa*0.25f+0.75f);
- F32 m = llmax(0.5f-spec*0.5f, 0.001f);
- F32 t2 = tanf(a)/m;
- t2 *= t2;
-
- F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
- F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
-
- lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+ F32 n = spec * spec * specExp;
+
+ // Nothing special here. Just your typical blinn-phong term.
+ spec = powf(sa, n);
+
+ // Apply our normalization function.
+ // Note: This is the full equation that applies the full normalization curve, not an approximation.
+ // This is fine, given we only need to create our LUT once per buffer initialization.
+ // The only trade off is we have a really low dynamic range.
+ // This means we have to account for things not being able to exceed 0 to 1 in our shaders.
+ spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n)));
+
+ // Always sample at a 1.0/2.2 curve.
+ // This "Gamma corrects" our specular term, boosting our lower exponent reflections.
+ spec = powf(spec, 1.f/2.2f);
+
+ // Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders.
+ // This allows for our specular term to exceed a value of 1 in our shaders.
+ // This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1.
+ // Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times.
+ // This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents.
+ // Combined with a bit of noise and trilinear filtering, the banding is hardly noticable.
+ ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255);
}
}
-
+
LLImageGL::generateTextures(1, &mLightFunc);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-
- delete [] lg;
+
+ delete [] ls;
}
}
-
- gBumpImageList.restoreGL();
}
-void LLPipeline::restoreGL()
+
+void LLPipeline::restoreGL()
{
LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
assertInitialized();
@@ -2523,15 +2556,6 @@ void LLPipeline::updateGeom(F32 max_dtime)
assertInitialized();
- if (sDelayedVBOEnable > 0)
- {
- if (--sDelayedVBOEnable <= 0)
- {
- resetVertexBuffers();
- LLVertexBuffer::sEnableVBOs = TRUE;
- }
- }
-
// notify various object types to reset internal cost metrics, etc.
// for now, only LLVOVolume does this to throttle LOD changes
LLVOVolume::preUpdateGeom();
@@ -3346,7 +3370,9 @@ void LLPipeline::postSort(LLCamera& camera)
{
LLSpatialGroup* group = *i;
if (sUseOcclusion &&
- group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED) ||
+ (RenderAutoHideSurfaceAreaLimit > 0.f &&
+ group->mSurfaceArea > RenderAutoHideSurfaceAreaLimit*llmax(group->mObjectBoxSize, 10.f)))
{
continue;
}
@@ -6185,7 +6211,7 @@ LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
{
- if (!drawable || drawable->isDead())
+ if (!drawable)
{
return;
}
@@ -6198,7 +6224,19 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
}
void LLPipeline::resetVertexBuffers()
-{
+{
+ mResetVertexBuffers = true;
+}
+
+void LLPipeline::doResetVertexBuffers()
+{
+ if (!mResetVertexBuffers)
+ {
+ return;
+ }
+
+ mResetVertexBuffers = false;
+
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
@@ -6224,11 +6262,9 @@ void LLPipeline::resetVertexBuffers()
if (LLVertexBuffer::sGLCount > 0)
{
- llwarns << "VBO wipe failed." << llendl;
+ llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl;
}
- llassert(LLVertexBuffer::sGLCount == 0);
-
LLVertexBuffer::unbind();
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
@@ -6646,9 +6682,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
mDeferredLight.flush();
}
+ U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale);
+ U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale);
+
{ //perform DoF sampling at half-res (preserve alpha channel)
mScreen.bindTarget();
- glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale));
+ glViewport(0,0, dof_width, dof_height);
gGL.setColorMask(true, false);
shader = &gDeferredPostProgram;
@@ -6661,7 +6700,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
+
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
gGL.vertex2f(-1,-1);
@@ -6706,6 +6745,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+ shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1);
+ shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
@@ -8259,7 +8300,7 @@ static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
-void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion, U32 target_width)
{
LLFastTimer t(FTM_SHADOW_RENDER);
@@ -8350,7 +8391,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LLFastTimer ftm(FTM_SHADOW_ALPHA);
gDeferredShadowAlphaMaskProgram.bind();
gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
-
+ gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+
U32 mask = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD0 |
LLVertexBuffer::MAP_COLOR |
@@ -8815,16 +8857,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
da = powf(da, split_exp.mV[2]);
-
F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
-
-
+
for (U32 i = 0; i < 4; ++i)
{
F32 x = (F32)(i+1)/4.f;
x = powf(x, sxp);
mSunClipPlanes.mV[i] = near_clip+range*x;
}
+
+ mSunClipPlanes.mV[0] *= 1.25f; //bump back first split for transition padding
}
// convenience array of 4 near clip plane distances
@@ -8881,8 +8923,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
delta.normVec();
F32 dp = delta*pn;
- frust[i] = eye + (delta*dist[j]*0.95f)/dp;
- frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
+ frust[i] = eye + (delta*dist[j]*0.75f)/dp;
+ frust[i+4] = eye + (delta*dist[j+1]*1.25f)/dp;
}
shadow_cam.calcAgentFrustumPlanes(frust);
@@ -9203,11 +9245,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadow[j].getViewport(gGLViewport);
mShadow[j].clear();
+ U32 target_width = mShadow[j].getWidth();
+
{
static LLCullResult result[4];
//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
- renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
+ renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width);
}
mShadow[j].flush();
@@ -9346,11 +9390,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadow[i+4].getViewport(gGLViewport);
mShadow[i+4].clear();
+ U32 target_width = mShadow[i+4].getWidth();
+
static LLCullResult result[2];
LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
- renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
+ renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
mShadow[i+4].flush();
}