diff options
Diffstat (limited to 'indra/newview/pipeline.cpp')
-rw-r--r-- | indra/newview/pipeline.cpp | 918 |
1 files changed, 667 insertions, 251 deletions
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6c9c4751d7..7b8739c7df 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -29,6 +29,7 @@ #include "pipeline.h" // library includes +#include "llimagepng.h" #include "llaudioengine.h" // For debugging. #include "llerror.h" #include "llviewercontrol.h" @@ -117,6 +118,20 @@ #include "llenvironment.h" #include "llsettingsvo.h" +#include "SMAAAreaTex.h" +#include "SMAASearchTex.h" + +#ifndef LL_WINDOWS +#define A_GCC 1 +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#if LL_LINUX +#pragma GCC diagnostic ignored "-Wrestrict" +#endif +#endif +#define A_CPU 1 +#include "app_settings/shaders/class1/deferred/CASF.glsl" // This is also C++ + extern bool gSnapshot; bool gShiftFrame = false; @@ -124,7 +139,7 @@ bool gShiftFrame = false; bool LLPipeline::WindLightUseAtmosShaders; bool LLPipeline::RenderDeferred; F32 LLPipeline::RenderDeferredSunWash; -U32 LLPipeline::RenderFSAASamples; +U32 LLPipeline::RenderFSAAType; U32 LLPipeline::RenderResolutionDivisor; bool LLPipeline::RenderUIBuffer; S32 LLPipeline::RenderShadowDetail; @@ -269,6 +284,7 @@ static LLStaticHashedString sDelta("delta"); static LLStaticHashedString sDistFactor("dist_factor"); static LLStaticHashedString sKern("kern"); static LLStaticHashedString sKernScale("kern_scale"); +static LLStaticHashedString sSmaaRTMetrics("SMAA_RT_METRICS"); //---------------------------------------- @@ -487,7 +503,7 @@ void LLPipeline::init() // DEPRECATED -- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); // DEPRECATED -- connectRefreshCachedSettingsSafe("RenderDeferred"); connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); - connectRefreshCachedSettingsSafe("RenderFSAASamples"); + connectRefreshCachedSettingsSafe("RenderFSAAType"); connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); connectRefreshCachedSettingsSafe("RenderUIBuffer"); connectRefreshCachedSettingsSafe("RenderShadowDetail"); @@ -725,40 +741,26 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) // refresh cached settings here to protect against inconsistent event handling order refreshCachedSettings(); - U32 samples = RenderFSAASamples; - eFBOStatus ret = FBO_SUCCESS_FULLRES; - if (!allocateScreenBuffer(resX, resY, samples)) + if (!allocateScreenBufferInternal(resX, resY)) { //failed to allocate at requested specification, return false ret = FBO_FAILURE; releaseScreenBuffers(); - //reduce number of samples - while (samples > 0) - { - samples /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { //success - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); - } - - samples = 0; //reduce resolution while (resY > 0 && resX > 0) { resY /= 2; - if (allocateScreenBuffer(resX, resY, samples)) + if (allocateScreenBufferInternal(resX, resY)) { return FBO_SUCCESS_LOWRES; } releaseScreenBuffers(); resX /= 2; - if (allocateScreenBuffer(resX, resY, samples)) + if (allocateScreenBufferInternal(resX, resY)) { return FBO_SUCCESS_LOWRES; } @@ -771,27 +773,29 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) return ret; } -bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) +bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; if (mRT == &mMainRT) { // hacky -- allocate auxillary buffer + + gCubeSnapshot = true; + if (sReflectionProbesEnabled) { - gCubeSnapshot = true; mReflectionMapManager.initReflectionMaps(); } mRT = &mAuxillaryRT; U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled - allocateScreenBuffer(res, res, samples); + allocateScreenBufferInternal(res, res); if (RenderMirrors) { mHeroProbeManager.initReflectionMaps(); res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it. mRT = &mHeroProbeRT; - allocateScreenBuffer(res, res, samples); + allocateScreenBufferInternal(res, res); } mRT = &mMainRT; @@ -810,17 +814,6 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) resY /= res_mod; } - //water reflection texture (always needed as scratch space whether or not transparent water is enabled) - mWaterDis.allocate(resX, resY, GL_RGBA16F, true); - - if (RenderUIBuffer) - { - if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA)) - { - return false; - } - } - S32 shadow_detail = RenderShadowDetail; bool ssao = RenderDeferredSSAO; @@ -834,17 +827,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mRT->deferredScreen.shareDepthBuffer(mRT->screen); - if (samples > 0) - { - if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA)) return false; - } - else - { - mRT->fxaaBuffer.release(); - } - - if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) - { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa + if (shadow_detail > 0 || ssao || RenderDepthOfField) + { //only need mRT->deferredLight for shadows OR ssao OR dof if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16F)) return false; } else @@ -854,15 +838,48 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) allocateShadowBuffer(resX, resY); - if (!gCubeSnapshot && RenderScreenSpaceReflections) // hack to not allocate mSceneMap for cube snapshots + if (!gCubeSnapshot) // hack to not re-allocate various targets for cube snapshots { - mSceneMap.allocate(resX, resY, GL_RGB, true); - } + if (RenderUIBuffer) + { + if (!mUIScreen.allocate(resX, resY, GL_RGBA)) + { + return false; + } + } - const bool post_hdr = gSavedSettings.getBOOL("RenderPostProcessingHDR"); - const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA; - mPostMap.allocate(resX, resY, post_color_fmt); + if (RenderFSAAType > 0) + { + if (!mFXAAMap.allocate(resX, resY, GL_RGBA)) return false; + if (RenderFSAAType == 2) + { + if (!mSMAABlendBuffer.allocate(resX, resY, GL_RGBA, false)) return false; + } + } + else + { + mFXAAMap.release(); + mSMAABlendBuffer.release(); + } + + //water reflection texture (always needed as scratch space whether or not transparent water is enabled) + mWaterDis.allocate(resX, resY, GL_RGBA16F, true); + if(RenderScreenSpaceReflections) + { + mSceneMap.allocate(resX, resY, GL_RGBA16F, true); + } + else + { + mSceneMap.release(); + } + + mPostMap.allocate(resX, resY, GL_RGBA16F); + + // used to scale down textures + // See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown + mDownResMap.allocate(4, 4, GL_RGBA); + } //HACK make screenbuffer allocations start failing after 30 seconds if (gSavedSettings.getBOOL("SimulateFBOFailure")) { @@ -884,7 +901,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; S32 shadow_detail = RenderShadowDetail; - F32 scale = llmax(0.f, RenderShadowResolutionScale); + F32 scale = gCubeSnapshot ? 1.0f : llmax(0.f, RenderShadowResolutionScale); // Don't scale probe shadow maps U32 sun_shadow_map_width = BlurHappySize(resX, scale); U32 sun_shadow_map_height = BlurHappySize(resY, scale); @@ -992,7 +1009,7 @@ void LLPipeline::refreshCachedSettings() WindLightUseAtmosShaders = true; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders"); RenderDeferred = true; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred"); RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); - RenderFSAASamples = LLFeatureManager::getInstance()->isFeatureAvailable("RenderFSAASamples") ? gSavedSettings.getU32("RenderFSAASamples") : 0; + RenderFSAAType = gSavedSettings.getU32("RenderFSAAType"); RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); @@ -1066,12 +1083,7 @@ void LLPipeline::refreshCachedSettings() RenderScreenSpaceReflectionAdaptiveStepMultiplier = gSavedSettings.getF32("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); RenderScreenSpaceReflectionGlossySamples = gSavedSettings.getS32("RenderScreenSpaceReflectionGlossySamples"); RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization"); - if (gSavedSettings.getBOOL("RenderMirrors") != RenderMirrors) - { - RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); - LLViewerShaderMgr::instance()->clearShaderCache(); - LLViewerShaderMgr::instance()->setShaders(); - } + RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); RenderHeroProbeUpdateRate = gSavedSettings.getS32("RenderHeroProbeUpdateRate"); RenderHeroProbeConservativeUpdateMultiplier = gSavedSettings.getS32("RenderHeroProbeConservativeUpdateMultiplier"); @@ -1101,6 +1113,18 @@ void LLPipeline::releaseGLBuffers() mTrueNoiseMap = 0; } + if (mSMAAAreaMap) + { + LLImageGL::deleteTextures(1, &mSMAAAreaMap); + mSMAAAreaMap = 0; + } + + if (mSMAASearchMap) + { + LLImageGL::deleteTextures(1, &mSMAASearchMap); + mSMAASearchMap = 0; + } + releaseLUTBuffers(); mWaterDis.release(); @@ -1109,11 +1133,19 @@ void LLPipeline::releaseGLBuffers() mPostMap.release(); + mFXAAMap.release(); + + mUIScreen.release(); + + mDownResMap.release(); + for (U32 i = 0; i < 3; i++) { mGlow[i].release(); } + mHeroProbeManager.cleanup(); // release hero probes + releaseScreenBuffers(); gBumpImageList.destroyGL(); @@ -1144,15 +1176,15 @@ void LLPipeline::releaseShadowBuffers() void LLPipeline::releaseScreenBuffers() { - mRT->uiScreen.release(); mRT->screen.release(); - mRT->fxaaBuffer.release(); mRT->deferredScreen.release(); mRT->deferredLight.release(); - mHeroProbeRT.uiScreen.release(); + mAuxillaryRT.screen.release(); + mAuxillaryRT.deferredScreen.release(); + mAuxillaryRT.deferredLight.release(); + mHeroProbeRT.screen.release(); - mHeroProbeRT.fxaaBuffer.release(); mHeroProbeRT.deferredScreen.release(); mHeroProbeRT.deferredLight.release(); } @@ -1233,7 +1265,7 @@ void LLPipeline::createGLBuffers() F32 noise[noiseRes*noiseRes*3]; for (U32 i = 0; i < noiseRes*noiseRes*3; i++) { - noise[i] = ll_frand()*2.0-1.0; + noise[i] = ll_frand()*2.0f-1.0f; } LLImageGL::generateTextures(1, &mTrueNoiseMap); @@ -1242,6 +1274,77 @@ void LLPipeline::createGLBuffers() gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + if (!mSMAAAreaMap) + { + std::vector<U8> tempBuffer(AREATEX_SIZE); + for (U32 y = 0; y < AREATEX_HEIGHT; y++) + { + U32 srcY = AREATEX_HEIGHT - 1 - y; + // unsigned int srcY = y; + memcpy(&tempBuffer[y * AREATEX_PITCH], areaTexBytes + srcY * AREATEX_PITCH, AREATEX_PITCH); + } + + LLImageGL::generateTextures(1, &mSMAAAreaMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mSMAAAreaMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG, + GL_UNSIGNED_BYTE, tempBuffer.data(), false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + + if (!mSMAASearchMap) + { + std::vector<U8> tempBuffer(SEARCHTEX_SIZE); + for (U32 y = 0; y < SEARCHTEX_HEIGHT; y++) + { + U32 srcY = SEARCHTEX_HEIGHT - 1 - y; + // unsigned int srcY = y; + memcpy(&tempBuffer[y * SEARCHTEX_PITCH], searchTexBytes + srcY * SEARCHTEX_PITCH, SEARCHTEX_PITCH); + } + + LLImageGL::generateTextures(1, &mSMAASearchMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mSMAASearchMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, + GL_RED, GL_UNSIGNED_BYTE, tempBuffer.data(), false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + + if (!mSMAASampleMap) + { + LLPointer<LLImageRaw> raw_image = new LLImageRaw; + LLPointer<LLImagePNG> png_image = new LLImagePNG; + static LLCachedControl<std::string> sample_path(gSavedSettings, "SamplePath", ""); + if (gDirUtilp->fileExists(sample_path()) && png_image->load(sample_path()) && png_image->decode(raw_image, 0.0f)) + { + U32 format = 0; + switch (raw_image->getComponents()) + { + case 1: + format = GL_RED; + break; + case 2: + format = GL_RG; + break; + case 3: + format = GL_RGB; + break; + case 4: + format = GL_RGBA; + break; + default: + return; + }; + LLImageGL::generateTextures(1, &mSMAASampleMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mSMAASampleMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB, raw_image->getWidth(), + raw_image->getHeight(), format, GL_UNSIGNED_BYTE, raw_image->getData(), false); + stop_glerror(); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + } + createLUTBuffers(); gBumpImageList.restoreGL(); @@ -3577,9 +3680,12 @@ void LLPipeline::postSort(LLCamera &camera) { mSelectedFaces.clear(); + bool tex_index_changed = false; if (!gNonInteractive) { - LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + LLRender::eTexIndex tex_index = sRenderHighlightTextureChannel; + setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + tex_index_changed = sRenderHighlightTextureChannel != tex_index; } // Draw face highlights for selected faces. @@ -3601,6 +3707,24 @@ void LLPipeline::postSort(LLCamera &camera) } } func; LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + + if (tex_index_changed) + { + // Rebuild geometry for all selected faces with PBR textures + for (const LLFace* face : gPipeline.mSelectedFaces) + { + if (const LLViewerObject* vobj = face->getViewerObject()) + { + if (const LLTextureEntry* tep = vobj->getTE(face->getTEOffset())) + { + if (tep->getGLTFRenderMaterial()) + { + gPipeline.markRebuild(face->getDrawable(), LLDrawable::REBUILD_VOLUME); + } + } + } + } + } } } @@ -3653,28 +3777,31 @@ void render_hud_elements() gUIProgram.unbind(); } -void LLPipeline::renderHighlights() +static inline void bindHighlightProgram(LLGLSLShader& program) { - assertInitialized(); - - // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) - // Render highlighted faces. - LLGLSPipelineAlpha gls_pipeline_alpha; - LLColor4 color(1.f, 1.f, 1.f, 0.5f); - disableLights(); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { - gHighlightProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); + program.bind(); + gGL.diffuseColor4f(1, 1, 1, 0.5f); } +} - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) - { - mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); - } +static inline void unbindHighlightProgram(LLGLSLShader& program) +{ + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) + { + program.unbind(); + } +} - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) +void LLPipeline::renderSelectedFaces(const LLColor4& color) +{ + if (!mFaceSelectImagep) + { + mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); + } + + if (mFaceSelectImagep) { // Make sure the selection image gets downloaded and decoded mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); @@ -3690,81 +3817,61 @@ void LLPipeline::renderHighlights() facep->renderSelected(mFaceSelectImagep, color); } } +} - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) - { - // Paint 'em red! - color.setVec(1.f, 0.f, 0.f, 0.5f); - - for (auto facep : mHighlightFaces) - { - facep->renderSelected(LLViewerTexture::sNullImagep, color); - } - } +void LLPipeline::renderHighlights() +{ + assertInitialized(); - // Contains a list of the faces of objects that are physical or - // have touch-handlers. - mHighlightFaces.clear(); + // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) + // Render highlighted faces. + LLGLSPipelineAlpha gls_pipeline_alpha; + disableLights(); - if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) { - gHighlightProgram.unbind(); - } - + bindHighlightProgram(gHighlightProgram); - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) - { - color.setVec(1.0f, 0.5f, 0.5f, 0.5f); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + if (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP || + sRenderHighlightTextureChannel == LLRender::BASECOLOR_MAP || + sRenderHighlightTextureChannel == LLRender::METALLIC_ROUGHNESS_MAP || + sRenderHighlightTextureChannel == LLRender::GLTF_NORMAL_MAP || + sRenderHighlightTextureChannel == LLRender::EMISSIVE_MAP || + sRenderHighlightTextureChannel == LLRender::NUM_TEXTURE_CHANNELS) { - gHighlightNormalProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); + static const LLColor4 highlight_selected_color(1.f, 1.f, 1.f, 0.5f); + renderSelectedFaces(highlight_selected_color); } - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); - - for (auto facep : mSelectedFaces) + // Paint 'em red! + static const LLColor4 highlight_face_color(1.f, 0.f, 0.f, 0.5f); + for (auto facep : mHighlightFaces) { - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } - - facep->renderSelected(mFaceSelectImagep, color); + facep->renderSelected(LLViewerTexture::sNullImagep, highlight_face_color); } - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightNormalProgram.unbind(); - } + unbindHighlightProgram(gHighlightProgram); } - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) - { - color.setVec(0.0f, 0.3f, 1.0f, 0.8f); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightSpecularProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } - - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + // Contains a list of the faces of objects that are physical or + // have touch-handlers. + mHighlightFaces.clear(); - for (auto facep : mSelectedFaces) + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) + { + if (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP) { - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } - - facep->renderSelected(mFaceSelectImagep, color); + static const LLColor4 highlight_normal_color(1.0f, 0.5f, 0.5f, 0.5f); + bindHighlightProgram(gHighlightNormalProgram); + renderSelectedFaces(highlight_normal_color); + unbindHighlightProgram(gHighlightNormalProgram); } - - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + else if (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP) { - gHighlightSpecularProgram.unbind(); + static const LLColor4 highlight_specular_color(0.0f, 0.3f, 1.0f, 0.8f); + bindHighlightProgram(gHighlightSpecularProgram); + renderSelectedFaces(highlight_specular_color); + unbindHighlightProgram(gHighlightSpecularProgram); } } } @@ -4502,33 +4609,51 @@ void LLPipeline::renderDebug() } // Debug stuff. - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | + LLPipeline::RENDER_DEBUG_OCCLUSION | + LLPipeline::RENDER_DEBUG_LIGHTS | + LLPipeline::RENDER_DEBUG_BATCH_SIZE | + LLPipeline::RENDER_DEBUG_UPDATE_TYPE | + LLPipeline::RENDER_DEBUG_BBOXES | + LLPipeline::RENDER_DEBUG_NORMALS | + LLPipeline::RENDER_DEBUG_POINTS | + LLPipeline::RENDER_DEBUG_TEXTURE_AREA | + LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | + LLPipeline::RENDER_DEBUG_RAYCAST | + LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | + LLPipeline::RENDER_DEBUG_AVATAR_JOINTS | + LLPipeline::RENDER_DEBUG_AGENT_TARGET | + LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | + LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("render debug bridges"); + + for (LLViewerRegion* region : LLWorld::getInstance()->getRegionList()) { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { - if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || - (!hud_only && hasRenderType(part->mDrawableType)) ) + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) { - part->renderDebug(); + if ((hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || + (!hud_only && hasRenderType(part->mDrawableType))) + { + part->renderDebug(); + } } } } - } - for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLSpatialBridge* bridge = *i; - if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - bridge->renderDebug(); - gGL.popMatrix(); + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderDebug(); + gGL.popMatrix(); + } } } @@ -4562,7 +4687,8 @@ void LLPipeline::renderDebug() mReflectionMapManager.renderDebug(); } - if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes") && !hud_only) + static LLCachedControl<bool> render_ref_probe_volumes(gSavedSettings, "RenderReflectionProbeVolumes"); + if (render_ref_probe_volumes && !hud_only) { LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("probe debug display"); @@ -5284,7 +5410,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; assertInitialized(); - if (LLPipeline::sReflectionRender || gCubeSnapshot || LLPipeline::sRenderingHUDs) + if (LLPipeline::sReflectionRender || gCubeSnapshot || LLPipeline::sRenderingHUDs || LLApp::isExiting()) { return; } @@ -6252,7 +6378,10 @@ bool LLPipeline::getRenderHighlights() // static void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel) { - sRenderHighlightTextureChannel = channel; + if (channel != sRenderHighlightTextureChannel) + { + sRenderHighlightTextureChannel = channel; + } } LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, @@ -6434,16 +6563,14 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, } } - //check all avatar nametags (silly, isn't it?) - for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); - ++iter) + // check all avatar nametags (silly, isn't it?) + for (LLCharacter* character : LLCharacter::sInstances) { - LLVOAvatar* av = (LLVOAvatar*) *iter; - if (av->mNameText.notNull() - && av->mNameText->lineSegmentIntersect(start, local_end, position)) + LLVOAvatar* avatar = (LLVOAvatar*)character; + if (avatar->mNameText.notNull() && + avatar->mNameText->lineSegmentIntersect(start, local_end, position)) { - drawable = av->mDrawable; + drawable = avatar->mDrawable; local_end = position; } } @@ -6603,8 +6730,14 @@ void LLPipeline::renderAlphaObjects(bool rigged) S32 sun_up = LLEnvironment::instance().getIsSunUp() ? 1 : 0; U32 target_width = LLRenderTarget::sCurResX; U32 type = LLRenderPass::PASS_ALPHA; - LLVOAvatar* lastAvatar = nullptr; + // for gDeferredShadowAlphaMaskProgram + const LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; + bool skipLastSkin; + // for gDeferredShadowGLTFAlphaBlendProgram + const LLVOAvatar* lastAvatarGLTF = nullptr; + U64 lastMeshIdGLTF = 0; + bool skipLastSkinGLTF; auto* begin = gPipeline.beginRenderMap(type); auto* end = gPipeline.endRenderMap(type); @@ -6628,7 +6761,7 @@ void LLPipeline::renderAlphaObjects(bool rigged) LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); - LLRenderPass::pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId); + LLRenderPass::pushRiggedGLTFBatch(*pparams, lastAvatarGLTF, lastMeshIdGLTF, skipLastSkinGLTF); } else { @@ -6636,14 +6769,10 @@ void LLPipeline::renderAlphaObjects(bool rigged) LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); - if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) + if (mSimplePool->uploadMatrixPalette(pparams->mAvatar, pparams->mSkinInfo, lastAvatar, lastMeshId, skipLastSkin)) { - mSimplePool->uploadMatrixPalette(*pparams); - lastAvatar = pparams->mAvatar; - lastMeshId = pparams->mSkinInfo->mHash; + mSimplePool->pushBatch(*pparams, true, true); } - - mSimplePool->pushBatch(*pparams, true, true); } } else @@ -6906,7 +7035,7 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool } } shader->uniform1f(dt, gFrameIntervalSeconds); - shader->uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); + shader->uniform2f(noiseVec, ll_frand() * 2.0f - 1.0f, ll_frand() * 2.0f - 1.0f); shader->uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, exp_min, exp_max); mScreenTriangleVB->setBuffer(); @@ -6923,11 +7052,12 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool extern LLPointer<LLImageGL> gEXRImage; -void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { +void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst) +{ dst->bindTarget(); // gamma correct lighting { - LL_PROFILE_GPU_ZONE("gamma correct"); + LL_PROFILE_GPU_ZONE("tonemap"); static LLCachedControl<bool> buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false); @@ -6940,9 +7070,7 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); bool no_post = gSnapshotNoPost || (buildNoPost && gFloaterTools->isAvailable()); - LLGLSLShader& shader = no_post ? gNoPostGammaCorrectProgram : // no post (no gamma, no exposure, no tonemapping) - psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? gLegacyPostGammaCorrectProgram : - gDeferredPostGammaCorrectProgram; + LLGLSLShader& shader = no_post ? gNoPostTonemapProgram : gDeferredPostTonemapProgram; shader.bind(); @@ -6952,17 +7080,23 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { shader.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap); - shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, src->getWidth(), src->getHeight()); + shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight()); static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f); F32 e = llclamp(exposure(), 0.5f, 4.f); static LLStaticHashedString s_exposure("exposure"); - static LLStaticHashedString aces_mix("aces_mix"); + static LLStaticHashedString tonemap_mix("tonemap_mix"); + static LLStaticHashedString tonemap_type("tonemap_type"); shader.uniform1f(s_exposure, e); - shader.uniform1f(aces_mix, gEXRImage.notNull() ? 0.f : 0.3f); + + static LLCachedControl<U32> tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U); + shader.uniform1i(tonemap_type, tonemap_type_setting); + + static LLCachedControl<F32> tonemap_mix_setting(gSavedSettings, "RenderTonemapMix", 1.f); + shader.uniform1f(tonemap_mix, tonemap_mix_setting); mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -6973,6 +7107,34 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { dst->flush(); } +void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) +{ + dst->bindTarget(); + // gamma correct lighting + { + LL_PROFILE_GPU_ZONE("gamma correct"); + + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + static LLCachedControl<bool> buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false); + static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); + + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + LLGLSLShader& shader = psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? gLegacyPostGammaCorrectProgram : + gDeferredPostGammaCorrectProgram; + + shader.bind(); + shader.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT); + shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)src->getWidth(), (GLfloat)src->getHeight()); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + shader.unbind(); + } + dst->flush(); +} + void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst) { @@ -7031,8 +7193,8 @@ void LLPipeline::generateGlow(LLRenderTarget* src) gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } gGlowExtractProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, - mGlow[2].getWidth(), - mGlow[2].getHeight()); + (GLfloat)mGlow[2].getWidth(), + (GLfloat)mGlow[2].getHeight()); } { @@ -7110,22 +7272,68 @@ void LLPipeline::generateGlow(LLRenderTarget* src) } } +void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst) +{ + static LLCachedControl<F32> cas_sharpness(gSavedSettings, "RenderCASSharpness", 0.4f); + if (cas_sharpness == 0.0f) + { + gPipeline.copyRenderTarget(src, dst); + return; + } + + LLGLSLShader* sharpen_shader = &gCASProgram; + + // Bind setup: + dst->bindTarget(); + + sharpen_shader->bind(); + + { + static LLStaticHashedString cas_param_0("cas_param_0"); + static LLStaticHashedString cas_param_1("cas_param_1"); + static LLStaticHashedString out_screen_res("out_screen_res"); + + varAU4(const0); + varAU4(const1); + CasSetup(const0, const1, + cas_sharpness(), // Sharpness tuning knob (0.0 to 1.0). + (AF1)src->getWidth(), (AF1)src->getHeight(), // Input size. + (AF1)dst->getWidth(), (AF1)dst->getHeight()); // Output size. + + sharpen_shader->uniform4uiv(cas_param_0, 1, const0); + sharpen_shader->uniform4uiv(cas_param_1, 1, const1); + + sharpen_shader->uniform2f(out_screen_res, (AF1)dst->getWidth(), (AF1)dst->getHeight()); + } + + sharpen_shader->bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT); + + // Draw + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + sharpen_shader->unbind(); + + dst->flush(); +} + void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) { { llassert(!gCubeSnapshot); - bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete(); + bool multisample = RenderFSAAType == 1 && mFXAAMap.isComplete(); LLGLSLShader* shader = &gGlowCombineProgram; - S32 width = dst->getWidth(); - S32 height = dst->getHeight(); - // Present everything. if (multisample) { LL_PROFILE_GPU_ZONE("aa"); + S32 width = dst->getWidth(); + S32 height = dst->getHeight(); + // bake out texture2D with RGBL for FXAA shader - mRT->fxaaBuffer.bindTarget(); + mFXAAMap.bindTarget(); + mFXAAMap.clear(GL_COLOR_BUFFER_BIT); shader = &gGlowCombineFXAAProgram; shader->bind(); @@ -7145,16 +7353,20 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); shader->unbind(); - mRT->fxaaBuffer.flush(); + mFXAAMap.flush(); dst->bindTarget(); - shader = &gFXAAProgram; + + static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U); + U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U); + + shader = &gFXAAProgram[fsaa_quality]; shader->bind(); - channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mRT->fxaaBuffer.getUsage()); + channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAAMap.getUsage()); if (channel > -1) { - mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); + mFXAAMap.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); } gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; @@ -7164,8 +7376,8 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - F32 scale_x = (F32)width / mRT->fxaaBuffer.getWidth(); - F32 scale_y = (F32)height / mRT->fxaaBuffer.getHeight(); + F32 scale_x = (F32)width / mFXAAMap.getWidth(); + F32 scale_y = (F32)height / mFXAAMap.getHeight(); shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y); shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y, @@ -7191,6 +7403,187 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) } } +void LLPipeline::generateSMAABuffers(LLRenderTarget* src) +{ + llassert(!gCubeSnapshot); + bool multisample = RenderFSAAType == 2 && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete(); + + // Present everything. + if (multisample) + { + LL_PROFILE_GPU_ZONE("aa"); + static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U); + U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U); + + S32 width = src->getWidth(); + S32 height = src->getHeight(); + + float rt_metrics[] = { 1.f / width, 1.f / height, (float)width, (float)height }; + + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + static LLCachedControl<bool> use_sample(gSavedSettings, "RenderSMAAUseSample", false); + //static LLCachedControl<bool> use_stencil(gSavedSettings, "RenderSMAAUseStencil", true); + { + //LLGLState stencil(GL_STENCIL_TEST, use_stencil); + + // Bind setup: + LLRenderTarget& dest = mFXAAMap; + LLGLSLShader& edge_shader = gSMAAEdgeDetectProgram[fsaa_quality]; + + dest.bindTarget(); + dest.clear(GL_COLOR_BUFFER_BIT); + + edge_shader.bind(); + edge_shader.uniform4fv(sSmaaRTMetrics, 1, rt_metrics); + + S32 channel = edge_shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); + if (channel > -1) + { + if (!use_sample) + { + src->bindTexture(0, channel, LLTexUnit::TFO_POINT); + gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + else + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mSMAASampleMap); + gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + } + + //if (use_stencil) + //{ + // glStencilFunc(GL_ALWAYS, 1, 0xFF); + // glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + // glStencilMask(0xFF); + //} + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + edge_shader.unbind(); + dest.flush(); + + gGL.getTexUnit(channel)->unbindFast(LLTexUnit::TT_TEXTURE); + } + + { + //LLGLState stencil(GL_STENCIL_TEST, use_stencil); + + // Bind setup: + LLRenderTarget& dest = mSMAABlendBuffer; + LLGLSLShader& blend_weights_shader = gSMAABlendWeightsProgram[fsaa_quality]; + + dest.bindTarget(); + dest.clear(GL_COLOR_BUFFER_BIT); + + blend_weights_shader.bind(); + blend_weights_shader.uniform4fv(sSmaaRTMetrics, 1, rt_metrics); + + S32 edge_tex_channel = blend_weights_shader.enableTexture(LLShaderMgr::SMAA_EDGE_TEX, mFXAAMap.getUsage()); + if (edge_tex_channel > -1) + { + mFXAAMap.bindTexture(0, edge_tex_channel, LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(edge_tex_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + S32 area_tex_channel = blend_weights_shader.enableTexture(LLShaderMgr::SMAA_AREA_TEX, LLTexUnit::TT_TEXTURE); + if (area_tex_channel > -1) + { + gGL.getTexUnit(area_tex_channel)->bindManual(LLTexUnit::TT_TEXTURE, mSMAAAreaMap); + gGL.getTexUnit(area_tex_channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(area_tex_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + S32 search_tex_channel = blend_weights_shader.enableTexture(LLShaderMgr::SMAA_SEARCH_TEX, LLTexUnit::TT_TEXTURE); + if (search_tex_channel > -1) + { + gGL.getTexUnit(search_tex_channel)->bindManual(LLTexUnit::TT_TEXTURE, mSMAASearchMap); + gGL.getTexUnit(search_tex_channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(search_tex_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + + //if (use_stencil) + //{ + // glStencilFunc(GL_EQUAL, 1, 0xFF); + // glStencilMask(0x00); + //} + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + //if (use_stencil) + //{ + // glStencilFunc(GL_ALWAYS, 0, 0xFF); + //} + blend_weights_shader.unbind(); + dest.flush(); + gGL.getTexUnit(edge_tex_channel)->unbindFast(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(area_tex_channel)->unbindFast(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(search_tex_channel)->unbindFast(LLTexUnit::TT_TEXTURE); + } + } +} + +void LLPipeline::applySMAA(LLRenderTarget* src, LLRenderTarget* dst) +{ + llassert(!gCubeSnapshot); + bool multisample = RenderFSAAType == 2 && mFXAAMap.isComplete() && mSMAABlendBuffer.isComplete(); + + // Present everything. + if (multisample) + { + LL_PROFILE_GPU_ZONE("aa"); + static LLCachedControl<U32> aa_quality(gSavedSettings, "RenderFSAASamples", 0U); + U32 fsaa_quality = std::clamp(aa_quality(), 0U, 3U); + + S32 width = src->getWidth(); + S32 height = src->getHeight(); + + float rt_metrics[] = { 1.f / width, 1.f / height, (float)width, (float)height }; + + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + static LLCachedControl<bool> use_sample(gSavedSettings, "RenderSMAAUseSample", false); + //static LLCachedControl<bool> use_stencil(gSavedSettings, "RenderSMAAUseStencil", true); + + { + //LLGLDisable stencil(GL_STENCIL_TEST); + + // Bind setup: + LLRenderTarget* bound_target = dst; + LLGLSLShader& blend_shader = gSMAANeighborhoodBlendProgram[fsaa_quality]; + + bound_target->bindTarget(); + bound_target->clear(GL_COLOR_BUFFER_BIT); + + blend_shader.bind(); + blend_shader.uniform4fv(sSmaaRTMetrics, 1, rt_metrics); + + S32 diffuse_channel = blend_shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); + if(diffuse_channel > -1) + { + src->bindTexture(0, diffuse_channel, LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } + + S32 blend_channel = blend_shader.enableTexture(LLShaderMgr::SMAA_BLEND_TEX); + if (blend_channel > -1) + { + mSMAABlendBuffer.bindTexture(0, blend_channel, LLTexUnit::TFO_BILINEAR); + } + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + bound_target->flush(); + blend_shader.unbind(); + gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(blend_channel)->unbindFast(LLTexUnit::TT_TEXTURE); + } + } + else + { + copyRenderTarget(src, dst); + } +} + void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst) { @@ -7357,7 +7750,7 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); - gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight()); gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle)); @@ -7383,7 +7776,7 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) gDeferredPostProgram.bind(); gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mRT->deferredLight, LLTexUnit::TFO_POINT); - gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight()); gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); @@ -7399,24 +7792,13 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) { // combine result based on alpha dst->bindTarget(); - if (RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete()) - { - glViewport(0, 0, dst->getWidth(), dst->getHeight()); - } - else - { - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - } + glViewport(0, 0, dst->getWidth(), dst->getHeight()); gDeferredDoFCombineProgram.bind(); gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mRT->deferredLight, LLTexUnit::TFO_POINT); - gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight()); gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth()); @@ -7458,20 +7840,27 @@ void LLPipeline::renderFinalize() gGL.setColorMask(true, true); glClearColor(0, 0, 0, 0); - copyScreenSpaceReflections(&mRT->screen, &mSceneMap); generateLuminance(&mRT->screen, &mLuminanceMap); generateExposure(&mLuminanceMap, &mExposureMap); + tonemap(&mRT->screen, &mPostMap); + + applyCAS(&mPostMap, &mRT->screen); + + generateSMAABuffers(&mRT->screen); + gammaCorrect(&mRT->screen, &mPostMap); LLVertexBuffer::unbind(); - generateGlow(&mPostMap); + applySMAA(&mPostMap, &mRT->screen); + + generateGlow(&mRT->screen); - combineGlow(&mPostMap, &mRT->screen); + combineGlow(&mRT->screen, &mPostMap); gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; @@ -7479,13 +7868,17 @@ void LLPipeline::renderFinalize() gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - renderDoF(&mRT->screen, &mPostMap); + renderDoF(&mPostMap, &mRT->screen); - applyFXAA(&mPostMap, &mRT->screen); LLRenderTarget* finalBuffer = &mRT->screen; - if (RenderBufferVisualization > -1) + if (RenderFSAAType == 1) { + applyFXAA(&mRT->screen, &mPostMap); finalBuffer = &mPostMap; + } + + if (RenderBufferVisualization > -1) + { switch (RenderBufferVisualization) { case 0: @@ -7496,6 +7889,23 @@ void LLPipeline::renderFinalize() break; case 4: visualizeBuffers(&mLuminanceMap, finalBuffer, 0); + break; + case 5: + { + if (RenderFSAAType > 0) + { + visualizeBuffers(&mFXAAMap, finalBuffer, 0); + } + break; + } + case 6: + { + if (RenderFSAAType == 2) + { + visualizeBuffers(&mSMAABlendBuffer, finalBuffer, 0); + } + break; + } default: break; } @@ -7503,11 +7913,11 @@ void LLPipeline::renderFinalize() // Present the screen target. - gDeferredPostNoDoFProgram.bind(); + gDeferredPostNoDoFNoiseProgram.bind(); // Add noise as part of final render to screen pass to avoid damaging other post effects // Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems. - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, finalBuffer); - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); + gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, finalBuffer); + gDeferredPostNoDoFNoiseProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); { LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); @@ -7515,7 +7925,7 @@ void LLPipeline::renderFinalize() mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); } - gDeferredPostNoDoFProgram.unbind(); + gDeferredPostNoDoFNoiseProgram.unbind(); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -7779,15 +8189,15 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize); shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale); + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, (GLfloat)RenderSSAOMaxScale); F32 ssao_factor = RenderSSAOFactor; shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor); + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0f/ssao_factor); LLVector3 ssao_effect = RenderSSAOEffect; - F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0; - F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0; + F32 matrix_diag = (ssao_effect[0] + 2.0f*ssao_effect[1])/3.0f; + F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0f; // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by // value factor, and scales remainder by saturation factor F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, @@ -7799,7 +8209,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; F32 shadow_bias = RenderShadowBias + shadow_bias_error; - shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_target->getWidth(), deferred_target->getHeight()); + shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)deferred_target->getWidth(), (GLfloat)deferred_target->getHeight()); shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, shadow_bias); @@ -7808,8 +8218,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV); shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV); - shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight()); - shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight()); + shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, (GLfloat)mRT->shadow[0].getWidth(), (GLfloat)mRT->shadow[0].getHeight()); + shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, (GLfloat)mSpotShadow[0].getWidth(), (GLfloat)mSpotShadow[0].getHeight()); shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); @@ -7907,13 +8317,15 @@ void LLPipeline::renderDeferredLighting() mat.mult_matrix_vec(tc_moon); mTransformedMoonDir.set(tc_moon.v); - if (RenderDeferredSSAO || RenderShadowDetail > 0) + if ((RenderDeferredSSAO && !gCubeSnapshot) || RenderShadowDetail > 0) { LL_PROFILE_GPU_ZONE("sun program"); deferred_light_target->bindTarget(); { // paint shadow/SSAO light map (direct lighting lightmap) LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - sun shadow"); - bindDeferredShader(gDeferredSunProgram, deferred_light_target); + + LLGLSLShader& sun_shader = gCubeSnapshot ? gDeferredSunProbeProgram : gDeferredSunProgram; + bindDeferredShader(sun_shader, deferred_light_target); mScreenTriangleVB->setBuffer(); glClearColor(1, 1, 1, 1); deferred_light_target->clear(GL_COLOR_BUFFER_BIT); @@ -7938,10 +8350,10 @@ void LLPipeline::renderDeferredLighting() } } - gDeferredSunProgram.uniform3fv(sOffset, slice, offset); - gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, - deferred_light_target->getWidth(), - deferred_light_target->getHeight()); + sun_shader.uniform3fv(sOffset, slice, offset); + sun_shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, + (GLfloat)deferred_light_target->getWidth(), + (GLfloat)deferred_light_target->getHeight()); { LLGLDisable blend(GL_BLEND); @@ -7949,12 +8361,12 @@ void LLPipeline::renderDeferredLighting() mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); } - unbindDeferredShader(gDeferredSunProgram); + unbindDeferredShader(sun_shader); } deferred_light_target->flush(); } - if (RenderDeferredSSAO) + if (RenderDeferredSSAO && !gCubeSnapshot) { // soften direct lighting lightmap LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow"); @@ -8640,7 +9052,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) { gGL.getTexUnit(channel)->bind(img); - F32 lod_range = logf(img->getWidth())/logf(2.f); + F32 lod_range = logf((F32)img->getWidth())/logf(2.f); shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus); shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range); @@ -8765,17 +9177,17 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) } - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ITR_COUNT, RenderScreenSpaceReflectionIterations); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ITR_COUNT, (GLfloat)RenderScreenSpaceReflectionIterations); shader.uniform1f(LLShaderMgr::DEFERRED_SSR_DIST_BIAS, RenderScreenSpaceReflectionDistanceBias); shader.uniform1f(LLShaderMgr::DEFERRED_SSR_RAY_STEP, RenderScreenSpaceReflectionRayStep); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_GLOSSY_SAMPLES, RenderScreenSpaceReflectionGlossySamples); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_GLOSSY_SAMPLES, (GLfloat)RenderScreenSpaceReflectionGlossySamples); shader.uniform1f(LLShaderMgr::DEFERRED_SSR_REJECT_BIAS, RenderScreenSpaceReflectionDepthRejectBias); mPoissonOffset++; if (mPoissonOffset > 128 - RenderScreenSpaceReflectionGlossySamples) mPoissonOffset = 0; - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_NOISE_SINE, mPoissonOffset); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_NOISE_SINE, (GLfloat)mPoissonOffset); shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ADAPTIVE_STEP_MULT, RenderScreenSpaceReflectionAdaptiveStepMultiplier); channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH); @@ -8957,7 +9369,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGL.diffuseColor4f(1, 1, 1, 1); - S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); + S32 shadow_detail = RenderShadowDetail; // if not using VSM, disable color writes if (shadow_detail <= 2) @@ -9941,7 +10353,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) { LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); F32 fade_amt = gFrameIntervalSeconds.value() - * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0); + * (F32)llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0); // should never happen llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull()); @@ -10108,8 +10520,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) for (U32 i = 0; i < 16; i++) { - gGLLastModelView[i] = last_modelview[i]; - gGLLastProjection[i] = last_projection[i]; + gGLLastModelView[i] = (F32)last_modelview[i]; + gGLLastProjection[i] = (F32)last_projection[i]; } popRenderTypeMask(); @@ -10570,10 +10982,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool sShadowRender = false; popRenderTypeMask(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + if (!preview_avatar) + { + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } if (!preview_avatar && !for_profile) { @@ -10656,6 +11071,7 @@ bool LLPipeline::hasAnyRenderType(U32 type, ...) const { if (mRenderTypeEnabled[type]) { + va_end(args); return true; } type = va_arg(args, U32); |