diff options
Diffstat (limited to 'indra/newview')
67 files changed, 5295 insertions, 825 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7d78ec9e3c..1a009967f5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -295,10 +295,12 @@ set(viewer_SOURCE_FILES llfloaterpathfindinglinksets.cpp llfloaterpathfindingobjects.cpp llfloaterpay.cpp + llfloaterperformance.cpp llfloaterperms.cpp llfloaterpostprocess.cpp llfloaterprofile.cpp llfloaterpreference.cpp + llfloaterpreferencesgraphicsadvanced.cpp llfloaterpreferenceviewadvanced.cpp llfloaterpreviewtrash.cpp llfloaterprofiletexture.cpp @@ -937,10 +939,12 @@ set(viewer_HEADER_FILES llfloaterpathfindinglinksets.h llfloaterpathfindingobjects.h llfloaterpay.h + llfloaterperformance.h llfloaterperms.h llfloaterpostprocess.h llfloaterprofile.h llfloaterpreference.h + llfloaterpreferencesgraphicsadvanced.h llfloaterpreferenceviewadvanced.h llfloaterpreviewtrash.h llfloaterprofiletexture.h @@ -1379,6 +1383,9 @@ set(viewer_HEADER_FILES VorbisFramework.h ) + list(APPEND viewer_SOURCE_FILES llperfstats.cpp) + list(APPEND viewer_HEADER_FILES llperfstats.h) + source_group("CMake Rules" FILES ViewerInstall.cmake) #build_data.json creation moved to viewer_manifest.py MAINT-6413 diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 2644f5f449..4a3dfffde1 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -285,4 +285,14 @@ is_running_function="Floater.IsOpen" is_running_parameters="360capture" /> + <command name="performance" + available_in_toybox="true" + icon="Command_Performance_Icon" + label_ref="Command_Performance_Label" + tooltip_ref="Command_Performance_Tooltip" + execute_function="Floater.ToggleOrBringToFront" + execute_parameters="performance" + is_running_function="Floater.IsOpen" + is_running_parameters="performance" + /> </commands> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6861153d43..657119ae53 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1415,7 +1415,7 @@ <key>Type</key> <string>U32</string> <key>Value</key> - <integer>1024</integer> + <integer>4096</integer> </map> <key>CacheValidateCounter</key> <map> @@ -8817,6 +8817,28 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderClass0MemoryBandwidth</key> + <map> + <key>Comment</key> + <string>Memory bandwidth at which to default to Class 0 in gigabytes per second. Used as basis for other classes.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>16.0</real> + </map> + <key>RenderCPUBasis</key> + <map> + <key>Comment</key> + <string>Reference CPU clockspeed to use to bias GPU class (in MHz).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>3000.0</real> + </map> <key>RenderComplexityColorMin</key> <map> <key>Comment</key> @@ -9074,6 +9096,17 @@ <key>Value</key> <real>0.5</real> </map> + <key>RenderShadowSplits</key> + <map> + <key>Comment</key> + <string>Amount of shadow map splits to render (0 - 3).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>3</integer> + </map> <key>RenderSSAOScale</key> <map> <key>Comment</key> @@ -16700,6 +16733,149 @@ <key>Value</key> <integer>0</integer> </map> + <key>TargetFPS</key> + <map> + <key>Comment</key> + <string>Desired minimum FPS</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>25</integer> + </map> + <key>AutoTuneFPS</key> + <map> + <key>Comment</key> + <string>Allow the viewer to adjust your settings to achieve target FPS</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>AutoTuneLock</key> + <map> + <key>Comment</key> + <string>When enabled the viewer will dynamically change settings until auto tune is explicitly turned off.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>AllowSelfImpostor</key> + <map> + <key>Comment</key> + <string>Allow own render time to impostor your avatar.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowTunedART</key> + <map> + <key>Comment</key> + <string>Show the current render time not the pre-tuning render time in the avatar display.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>RenderAvatarMaxART</key> + <map> + <key>Comment</key> + <string>Render Time Limit in microseconds (0.0 = no limit)</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>4.699</real> + </map> + <key>AutoTuneRenderFarClipMin</key> + <map> + <key>Comment</key> + <string>The lowest draw distance that auto tune is allowed to use</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>32.0</real> + </map> + <key>AutoTuneRenderFarClipTarget</key> + <map> + <key>Comment</key> + <string>The draw distance that auto tune will try to achieve</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>256.0</real> + </map> + <key>UserTargetReflections</key> + <map> + <key>Comment</key> + <string>Set by auto tune floater on build</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>4</integer> + </map> + <key>PerfStatsCaptureEnabled</key> + <map> + <key>Comment</key> + <string>Enable/disable render time data to support autotune.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>AutoTuneImpostorByDistEnabled</key> + <map> + <key>Comment</key> + <string>Enable/disable using MaxNonImpostor to limit avatar rendering by distance.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>AutoTuneImpostorFarAwayDistance</key> + <map> + <key>Comment</key> + <string>Avatars beyond this range will automatically be optimized</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>64.0</real> + </map> + <key>TuningFPSStrategy</key> + <map> + <key>Comment</key> + <string>Strategy to use when tuning FPS. 0=Tune avatar rendering only, 1=Tune both avatar and global scene settings.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>CameraOpacity</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml index f3a23edc58..a1c9d6d9ee 100644 --- a/indra/newview/app_settings/toolbars.xml +++ b/indra/newview/app_settings/toolbars.xml @@ -22,6 +22,7 @@ <command name="voice"/> <command name="minimap"/> <command name="snapshot"/> + <command name="performance"/> </left_toolbar> <right_toolbar button_display_mode="icons_only"> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 1ccde98283..ff7ac84803 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -113,6 +113,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 RenderAvatarMaxComplexity 1 100000 RenderAvatarPhysicsLODFactor 1 0.75 +RenderAvatarMaxNonImpostors 1 5 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 @@ -142,6 +143,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 200000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 7 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -153,7 +155,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.25 WindLightUseAtmosShaders 1 1 RenderDeferred 1 0 RenderDeferredSSAO 1 0 @@ -171,6 +173,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 250000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 9 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -182,7 +185,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.375 WindLightUseAtmosShaders 1 1 RenderDeferred 1 1 RenderDeferredSSAO 1 0 @@ -200,6 +203,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 300000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 11 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -211,7 +215,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.5 WindLightUseAtmosShaders 1 1 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -229,6 +233,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 350000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 16 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -240,7 +245,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.75 WindLightUseAtmosShaders 1 1 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -256,6 +261,7 @@ list Ultra RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 16 RenderAvatarPhysicsLODFactor 1 1.0 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index c9efd89cc8..248eb68ee9 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -112,6 +112,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 RenderAvatarMaxComplexity 1 100000 RenderAvatarPhysicsLODFactor 1 0.75 +RenderAvatarMaxNonImpostors 1 5 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 @@ -141,6 +142,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 200000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 7 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -152,7 +154,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.25 WindLightUseAtmosShaders 1 1 RenderDeferred 1 0 RenderDeferredSSAO 1 0 @@ -170,6 +172,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 250000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 9 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -181,7 +184,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.375 WindLightUseAtmosShaders 1 1 RenderDeferred 1 1 RenderDeferredSSAO 1 0 @@ -199,6 +202,7 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 300000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 11 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -210,7 +214,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.5 WindLightUseAtmosShaders 1 1 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -226,6 +230,7 @@ list HighUltra RenderAnisotropic 1 1 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 350000 RenderAvatarPhysicsLODFactor 1 1.0 RenderFarClip 1 128 @@ -239,7 +244,7 @@ RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 +RenderVolumeLODFactor 1 1.75 WindLightUseAtmosShaders 1 1 RenderDeferred 1 1 RenderDeferredSSAO 1 1 @@ -256,6 +261,7 @@ RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 16 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 5250369813..5a30c7d9cd 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4100,6 +4100,7 @@ void LLAgent::handleTeleportFinished() mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport)); } } + } void LLAgent::handleTeleportFailed() @@ -4131,6 +4132,7 @@ void LLAgent::handleTeleportFailed() } mTPNeedsNeabyChatSeparator = false; + } /*static*/ diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4f3e0b08e4..aef78e08e6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -108,6 +108,7 @@ #include "llscenemonitor.h" #include "llavatarrenderinfoaccountant.h" #include "lllocalbitmaps.h" +#include "llperfstats.h" // Linden library includes #include "llavatarnamecache.h" @@ -1377,82 +1378,91 @@ bool LLAppViewer::frame() bool LLAppViewer::doFrame() { - LL_RECORD_BLOCK_TIME(FTM_FRAME); + LL_RECORD_BLOCK_TIME(FTM_FRAME); + { + // and now adjust the visuals from previous frame. + if(LLPerfStats::tunables.userAutoTuneEnabled && LLPerfStats::tunables.tuningFlag != LLPerfStats::Tunables::Nothing) + { + LLPerfStats::tunables.applyUpdates(); + } + LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_FRAME); if (!LLWorld::instanceExists()) { LLWorld::createInstance(); } - LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); - LLSD newFrame; - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df LLTrace"); - if (LLFloaterReg::instanceVisible("block_timers")) + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); + LLSD newFrame; + { + LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE); // perf stats { - LLTrace::BlockTimer::processTimes(); - } - - LLTrace::get_frame_recording().nextPeriod(); - LLTrace::BlockTimer::logStats(); - } + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df LLTrace"); + if (LLFloaterReg::instanceVisible("block_timers")) + { + LLTrace::BlockTimer::processTimes(); + } - LLTrace::get_thread_recorder()->pullFromChildren(); + LLTrace::get_frame_recording().nextPeriod(); + LLTrace::BlockTimer::logStats(); + } - //clear call stack records - LL_CLEAR_CALLSTACKS(); + LLTrace::get_thread_recorder()->pullFromChildren(); - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df processMiscNativeEvents" ) - pingMainloopTimeout("Main:MiscNativeWindowEvents"); + //clear call stack records + LL_CLEAR_CALLSTACKS(); + } + { + { + LLPerfStats::RecordSceneTime T(LLPerfStats::StatType_t::RENDER_IDLE); // ensure we have the entire top scope of frame covered (input event and coro) + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df processMiscNativeEvents") + pingMainloopTimeout("Main:MiscNativeWindowEvents"); - if (gViewerWindow) - { - LL_RECORD_BLOCK_TIME(FTM_MESSAGES); - gViewerWindow->getWindow()->processMiscNativeEvents(); - } + if (gViewerWindow) + { + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); + gViewerWindow->getWindow()->processMiscNativeEvents(); + } - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df gatherInput" ) - pingMainloopTimeout("Main:GatherInput"); - } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df gatherInput") + pingMainloopTimeout("Main:GatherInput"); + } - if (gViewerWindow) - { - LL_RECORD_BLOCK_TIME(FTM_MESSAGES); - if (!restoreErrorTrap()) - { - LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; - } + if (gViewerWindow) + { + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); + if (!restoreErrorTrap()) + { + LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; + } - gViewerWindow->getWindow()->gatherInput(); - } + gViewerWindow->getWindow()->gatherInput(); + } - //memory leaking simulation - if (gSimulateMemLeak) - { - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); - if (mem_leak_instance) - { - mem_leak_instance->idle(); - } - } + //memory leaking simulation + if (gSimulateMemLeak) + { + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if (mem_leak_instance) + { + mem_leak_instance->idle(); + } + } - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df mainloop" ) - // canonical per-frame event - mainloop.post(newFrame); - } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df mainloop") + // canonical per-frame event + mainloop.post(newFrame); + } - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df suspend" ) - // give listeners a chance to run - llcoro::suspend(); - // if one of our coroutines threw an uncaught exception, rethrow it now - LLCoros::instance().rethrow(); - } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df suspend") + // give listeners a chance to run + llcoro::suspend(); + } + } if (!LLApp::isExiting()) { @@ -1470,6 +1480,7 @@ bool LLAppViewer::doFrame() && (gHeadlessClient || !gViewerWindow->getShowProgress()) && !gFocusMgr.focusLocked()) { + LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE); joystick->scanJoystick(); gKeyboard->scanKeyboard(); gViewerInput.scanMouse(); @@ -1483,6 +1494,7 @@ bool LLAppViewer::doFrame() } { + LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE); LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle"); //LL_RECORD_BLOCK_TIME(FTM_IDLE); idle(); } @@ -1517,13 +1529,14 @@ bool LLAppViewer::doFrame() display(); - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" ) - pingMainloopTimeout("Main:Snapshot"); - LLFloaterSnapshot::update(); // take snapshots - LLFloaterOutfitSnapshot::update(); - gGLActive = FALSE; - } + { + LLPerfStats::RecordSceneTime T(LLPerfStats::StatType_t::RENDER_IDLE); + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" ) + pingMainloopTimeout("Main:Snapshot"); + LLFloaterSnapshot::update(); // take snapshots + LLFloaterOutfitSnapshot::update(); + gGLActive = FALSE; + } } } @@ -1569,7 +1582,8 @@ bool LLAppViewer::doFrame() // of equal priority on Windows if (milliseconds_to_sleep > 0) { - ms_sleep(milliseconds_to_sleep); + LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_SLEEP ); + ms_sleep(milliseconds_to_sleep); // also pause worker threads during this wait period LLAppViewer::getTextureCache()->pause(); LLAppViewer::getImageDecodeThread()->pause(); @@ -1670,7 +1684,7 @@ bool LLAppViewer::doFrame() LL_INFOS() << "Exiting main_loop" << LL_ENDL; } - + }LLPerfStats::StatsRecorder::endFrame(); LL_PROFILER_FRAME_END return ! LLApp::isRunning(); diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp index 94584a623b..8b09f7903d 100644 --- a/indra/newview/llavatarrendernotifier.cpp +++ b/indra/newview/llavatarrendernotifier.cpp @@ -235,6 +235,12 @@ void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity) // save the value for use in following messages mLatestAgentComplexity = agentComplexity; + static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20); + if (!show_my_complexity_changes) + { + return; + } + if (!isAgentAvatarValid() || !gAgentWearables.areWearablesLoaded()) { // data not ready, nothing to show. @@ -282,7 +288,8 @@ static const char* e_hud_messages[] = }; LLHUDRenderNotifier::LLHUDRenderNotifier() : -mReportedHUDWarning(WARN_NONE) +mReportedHUDWarning(WARN_NONE), +mHUDsCount(0) { } @@ -298,6 +305,15 @@ void LLHUDRenderNotifier::updateNotificationHUD(hud_complexity_list_t complexity return; } + mHUDComplexityList = complexity; + mHUDsCount = mHUDComplexityList.size(); + + static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20); + if (!show_my_complexity_changes) + { + return; + } + // TODO: // Find a way to show message with list of issues, but without making it too large // and intrusive. diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h index ec17b3d9e6..37130bfcf6 100644 --- a/indra/newview/llavatarrendernotifier.h +++ b/indra/newview/llavatarrendernotifier.h @@ -63,6 +63,25 @@ struct LLHUDComplexity typedef std::list<LLHUDComplexity> hud_complexity_list_t; +struct LLObjectComplexity +{ + LLObjectComplexity() + { + reset(); + } + void reset() + { + objectId = LLUUID::null; + objectName = ""; + objectCost = 0; + } + LLUUID objectId; + std::string objectName; + U32 objectCost; +}; + +typedef std::list<LLObjectComplexity> object_complexity_list_t; + // Class to notify user about drastic changes in agent's render weights or if other agents // reported that user's agent is too 'heavy' for their settings class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier> @@ -77,6 +96,9 @@ public: void updateNotificationState(); void updateNotificationAgent(U32 agentComplexity); + void setObjectComplexityList(object_complexity_list_t object_list) { mObjectComplexityList = object_list; } + object_complexity_list_t getObjectComplexityList() { return mObjectComplexityList; } + private: LLNotificationPtr mNotificationPtr; @@ -109,6 +131,8 @@ private: // Used to detect changes in voavatar's rezzed status. // If value decreases - there were changes in outfit. S32 mLastOutfitRezStatus; + + object_complexity_list_t mObjectComplexityList; }; // Class to notify user about heavy set of HUD @@ -121,6 +145,9 @@ public: void updateNotificationHUD(hud_complexity_list_t complexity); bool isNotificationVisible(); + hud_complexity_list_t getHUDComplexityList() { return mHUDComplexityList; } + S32 getHUDsCount() { return mHUDsCount; } + private: enum EWarnLevel { @@ -141,6 +168,8 @@ private: EWarnLevel mReportedHUDWarning; LLHUDComplexity mLatestHUDComplexity; LLFrameTimer mHUDPopUpDelayTimer; + hud_complexity_list_t mHUDComplexityList; + S32 mHUDsCount; }; #endif /* ! defined(LL_llavatarrendernotifier_H) */ diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index a3837fe10c..594cfe513d 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -52,6 +52,7 @@ #include "llglcommonfunc.h" #include "llvoavatar.h" #include "llviewershadermgr.h" +#include "llperfstats.h" S32 LLDrawPool::sNumDrawPools = 0; @@ -391,13 +392,22 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL t { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - + + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Perf stats for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo *pparams = *k; if (pparams) { - pushBatch(*pparams, mask, texture); + if(pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments(vobj, false, &ratPtr); + } + } + pushBatch(*pparams, mask, texture); } } } @@ -410,11 +420,21 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, U64 lastMeshId = 0; mask |= LLVertexBuffer::MAP_WEIGHT4; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Perf stats for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo* pparams = *k; if (pparams) { + if(pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments( vobj, true ,&ratPtr); + } + } + if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) { uploadMatrixPalette(*pparams); @@ -430,12 +450,21 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { - pushBatch(*pparams, mask, texture, batch_textures); + if(pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments( vobj, false, &ratPtr); + } + } + pushBatch(*pparams, mask, texture, batch_textures); } } } @@ -446,11 +475,21 @@ void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batc LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; mask |= LLVertexBuffer::MAP_WEIGHT4; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Perf stats for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { + if(pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments( vobj, true, &ratPtr); + } + } + if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)) { uploadMatrixPalette(*pparams); @@ -466,11 +505,20 @@ void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batc void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { + if((*pparams).mFace) + { + LLViewerObject* vobj = (*pparams).mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments( vobj, false, &ratPtr); + } + } LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); pushBatch(*pparams, mask, texture, batch_textures); } @@ -482,11 +530,20 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture, BOOL LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { + if((*pparams).mFace) + { + LLViewerObject* vobj = (*pparams).mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments( vobj, true, &ratPtr); + } + } if (LLGLSLShader::sCurBoundShaderPtr) { LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 6c1abb24c9..5b205d373b 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -49,6 +49,7 @@ #include "llspatialpartition.h" #include "llglcommonfunc.h" #include "llvoavatar.h" +#include "llperfstats.h" BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; @@ -338,10 +339,20 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA+pass]; // <-- hacky + pass to use PASS_ALPHA_RIGGED on second pass + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Render time Stats collection for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo& params = **k; + if(params.mFace) + { + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + if(vobj->isAttachment()) + { + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + } + } + if (params.mParticle) { continue; @@ -511,8 +522,16 @@ void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& mask |= LLVertexBuffer::MAP_WEIGHT4; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Render time Stats collection for (LLDrawInfo* draw : emissives) { + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("Emissives"); + auto vobj = draw->mFace?draw->mFace->getViewerObject():nullptr; + if(vobj && vobj->isAttachment()) + { + trackAttachments( vobj, draw->mFace->isState(LLFace::RIGGED), &ratPtr ); + } + bool tex_setup = TexSetup(draw, false); if (lastAvatar != draw->mAvatar || lastMeshId != draw->mSkinInfo->mHash) { @@ -577,7 +596,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA]; - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; // Render time Stats collection + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo& params = **k; if ((bool)params.mAvatar != rigged) @@ -596,6 +616,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) continue; } + if(params.mFace) + { + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + + if(vobj->isAttachment()) + { + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + } + } + if(depth_only) { // when updating depth buffer, discard faces that are more than 90% transparent @@ -780,6 +810,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) } } + ratPtr.reset(); // force the final batch to terminate to avoid double counting on the subsidiary batches for FB and Emmissives + // render emissive faces into alpha channel for bloom effects if (!depth_only) { diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 4a9a3caaec..02dea6b828 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -52,6 +52,7 @@ #include "llviewerpartsim.h" #include "llviewercontrol.h" // for gSavedSettings #include "llviewertexturelist.h" +#include "llperfstats.h" static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; @@ -380,9 +381,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) { return; } + LLPerfStats::RecordAvatarTime T(avatarp->getID(), LLPerfStats::StatType_t::RENDER_SHADOWS); + LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance(); - BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor(); - if (impostor || (oa == LLVOAvatar::AOA_INVISIBLE)) + BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor(); + // no shadows if the shadows are causing this avatar to breach the limit. + if (avatarp->isTooSlowWithShadows() || impostor || (oa == LLVOAvatar::AOA_INVISIBLE)) { // No shadows for impostored (including jellydolled) or invisible avs. return; @@ -789,6 +793,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { return; } + LLPerfStats::RecordAvatarTime T(avatarp->getID(), LLPerfStats::StatType_t::RENDER_GEOMETRY); if (!single_avatar && !avatarp->isFullyLoaded() ) { diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 8db6a10e26..09b2400aff 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -48,6 +48,7 @@ #include "llspatialpartition.h" #include "llviewershadermgr.h" #include "llmodel.h" +#include "llperfstats.h" //#include "llimagebmp.h" //#include "../tools/imdebug/imdebug.h" @@ -538,10 +539,18 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL { LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo& params = **k; + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + + if( vobj && vobj->isAttachment() ) + { + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + } + applyModelMatrix(params); if (params.mGroup) @@ -706,10 +715,21 @@ void LLDrawPoolBump::renderDeferred(S32 pass) LLVOAvatar* avatar = nullptr; U64 skin = 0; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; + if(params.mFace) + { + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + + if(vobj && vobj->isAttachment()) + { + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + } + } + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff); LLDrawPoolBump::bindBumpMap(params, bump_channel); @@ -1337,10 +1357,21 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; + if(params.mFace) + { + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + + if( vobj && vobj->isAttachment() ) + { + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + } + } + if (LLDrawPoolBump::bindBumpMap(params)) { if (mRigged) diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 2b05f4c453..f2408a3294 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -32,6 +32,7 @@ #include "pipeline.h" #include "llglcommonfunc.h" #include "llvoavatar.h" +#include "llperfstats.h" S32 diffuse_channel = -1; @@ -164,9 +165,20 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; + + if(params.mFace) + { + LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); + + if( vobj && vobj->isAttachment() ) + { + trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + } + } mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]); mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity); diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index e934041e2e..329af264eb 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -408,6 +408,7 @@ bool LLFeatureManager::loadGPUClass() { if (!gSavedSettings.getBOOL("SkipBenchmark")) { + F32 class0_gbps = gSavedSettings.getF32("RenderClass0MemoryBandwidth"); //get memory bandwidth from benchmark F32 gbps; try @@ -424,6 +425,14 @@ bool LLFeatureManager::loadGPUClass() LL_WARNS("RenderInit") << "GPU benchmark failed: " << e.what() << LL_ENDL; } + mGPUMemoryBandwidth = gbps; + + // bias by CPU speed + F32 cpu_basis_mhz = gSavedSettings.getF32("RenderCPUBasis"); + F32 cpu_mhz = (F32) gSysCPU.getMHz(); + F32 cpu_bias = llclamp(cpu_mhz / cpu_basis_mhz, 0.5f, 1.f); + gbps *= cpu_bias; + if (gbps < 0.f) { //couldn't bench, use GLVersion #if LL_DARWIN @@ -466,23 +475,23 @@ bool LLFeatureManager::loadGPUClass() { mGPUClass = GPU_CLASS_1; } - else if (gbps <= 5.f) + else if (gbps <= class0_gbps) { mGPUClass = GPU_CLASS_0; } - else if (gbps <= 8.f) + else if (gbps <= class0_gbps*2.f) { mGPUClass = GPU_CLASS_1; } - else if (gbps <= 16.f) + else if (gbps <= class0_gbps*4.f) { mGPUClass = GPU_CLASS_2; } - else if (gbps <= 40.f) + else if (gbps <= class0_gbps*8.f) { mGPUClass = GPU_CLASS_3; } - else if (gbps <= 80.f) + else if (gbps <= class0_gbps*16.f) { mGPUClass = GPU_CLASS_4; } diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 42a226cd18..651404d890 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -111,6 +111,10 @@ public: EGPUClass getGPUClass() { return mGPUClass; } std::string& getGPUString() { return mGPUString; } + + // get the measured GPU memory bandwidth in GB/sec + // may return 0 of benchmark has not been run or failed to run + F32 getGPUMemoryBandwidth() { return mGPUMemoryBandwidth; } BOOL isGPUSupported() { return mGPUSupported; } F32 getExpectedGLVersion() { return mExpectedGLVersion; } @@ -162,6 +166,7 @@ protected: S32 mTableVersion; BOOL mSafe; // Reinitialize everything to the "safe" mask EGPUClass mGPUClass; + F32 mGPUMemoryBandwidth = 0.f; // measured memory bandwidth of GPU in GB/second F32 mExpectedGLVersion; //expected GL version according to gpu table std::string mGPUString; BOOL mGPUSupported; diff --git a/indra/newview/llfloateravatarrendersettings.cpp b/indra/newview/llfloateravatarrendersettings.cpp index b8f854feb3..7d098e6c88 100644 --- a/indra/newview/llfloateravatarrendersettings.cpp +++ b/indra/newview/llfloateravatarrendersettings.cpp @@ -89,7 +89,6 @@ BOOL LLFloaterAvatarRenderSettings::postBuild() LLFloater::postBuild(); mAvatarSettingsList = getChild<LLNameListCtrl>("render_settings_list"); mAvatarSettingsList->setRightMouseDownCallback(boost::bind(&LLFloaterAvatarRenderSettings::onAvatarListRightClick, this, _1, _2, _3)); - getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterAvatarRenderSettings::onFilterEdit, this, _2)); return TRUE; } @@ -133,37 +132,13 @@ void LLFloaterAvatarRenderSettings::updateList() { item_params.value = iter->first; LLAvatarNameCache::get(iter->first, &av_name); - if(!isHiddenRow(av_name.getCompleteName())) - { - item_params.columns.add().value(av_name.getCompleteName()).column("name"); - std::string setting = getString(iter->second == 1 ? "av_never_render" : "av_always_render"); - item_params.columns.add().value(setting).column("setting"); - std::string timestamp = createTimestamp(LLRenderMuteList::getInstance()->getVisualMuteDate(iter->first)); - item_params.columns.add().value(timestamp).column("timestamp"); - mAvatarSettingsList->addNameItemRow(item_params); - } + item_params.columns.add().value(av_name.getCompleteName()).column("name"); + std::string setting = getString(iter->second == 1 ? "av_never_render" : "av_always_render"); + item_params.columns.add().value(setting).column("setting"); + mAvatarSettingsList->addNameItemRow(item_params); } } -void LLFloaterAvatarRenderSettings::onFilterEdit(const std::string& search_string) -{ - std::string filter_upper = search_string; - LLStringUtil::toUpper(filter_upper); - if (mNameFilter != filter_upper) - { - mNameFilter = filter_upper; - mNeedsUpdate = true; - } -} - -bool LLFloaterAvatarRenderSettings::isHiddenRow(const std::string& av_name) -{ - if (mNameFilter.empty()) return false; - std::string upper_name = av_name; - LLStringUtil::toUpper(upper_name); - return std::string::npos == upper_name.find(mNameFilter); -} - static LLVOAvatar* find_avatar(const LLUUID& id) { LLViewerObject *obj = gObjectList.findObject(id); @@ -214,6 +189,10 @@ bool LLFloaterAvatarRenderSettings::isActionChecked(const LLSD& userdata, const { return (visual_setting == S32(LLVOAvatar::AV_RENDER_NORMALLY)); } + else if ("non_default" == command_name) + { + return (visual_setting != S32(LLVOAvatar::AV_RENDER_NORMALLY)); + } else if ("never" == command_name) { return (visual_setting == S32(LLVOAvatar::AV_DO_NOT_RENDER)); diff --git a/indra/newview/llfloateravatarrendersettings.h b/indra/newview/llfloateravatarrendersettings.h index 00ee074f17..2e0a844afd 100644 --- a/indra/newview/llfloateravatarrendersettings.h +++ b/indra/newview/llfloateravatarrendersettings.h @@ -48,7 +48,6 @@ public: void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y); void updateList(); - void onFilterEdit(const std::string& search_string); void onCustomAction (const LLSD& userdata, const LLUUID& av_id); bool isActionChecked(const LLSD& userdata, const LLUUID& av_id); void onClickAdd(const LLSD& userdata); @@ -59,15 +58,12 @@ public: static void setNeedsUpdate(); private: - bool isHiddenRow(const std::string& av_name); void callbackAvatarPicked(const uuid_vec_t& ids, S32 visual_setting); void removePicker(); bool mNeedsUpdate; LLListContextMenu* mContextMenu; LLNameListCtrl* mAvatarSettingsList; - - std::string mNameFilter; }; diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp new file mode 100644 index 0000000000..10595f5b6a --- /dev/null +++ b/indra/newview/llfloaterperformance.cpp @@ -0,0 +1,638 @@ +/** + * @file llfloaterperformance.cpp + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterperformance.h" + +#include "llagent.h" +#include "llagentcamera.h" +#include "llappearancemgr.h" +#include "llavataractions.h" +#include "llavatarrendernotifier.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llfeaturemanager.h" +#include "llfloaterpreference.h" // LLAvatarComplexityControls +#include "llfloaterreg.h" +#include "llnamelistctrl.h" +#include "llnotificationsutil.h" +#include "llperfstats.h" +#include "llradiogroup.h" +#include "llsliderctrl.h" +#include "lltextbox.h" +#include "lltrans.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llvoavatarself.h" +#include "llworld.h" +#include "pipeline.h" + +const F32 REFRESH_INTERVAL = 1.0f; +const S32 BAR_LEFT_PAD = 2; +const S32 BAR_RIGHT_PAD = 5; +const S32 BAR_BOTTOM_PAD = 9; + +constexpr auto AvType {LLPerfStats::ObjType_t::OT_AVATAR}; +constexpr auto AttType {LLPerfStats::ObjType_t::OT_ATTACHMENT}; +constexpr auto HudType {LLPerfStats::ObjType_t::OT_HUD}; + +class LLExceptionsContextMenu : public LLListContextMenu +{ +public: + LLExceptionsContextMenu(LLFloaterPerformance* floater_settings) + : mFloaterPerformance(floater_settings) + {} +protected: + LLContextMenu* createMenu() + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + registrar.add("Settings.SetRendering", boost::bind(&LLFloaterPerformance::onCustomAction, mFloaterPerformance, _2, mUUIDs.front())); + enable_registrar.add("Settings.IsSelected", boost::bind(&LLFloaterPerformance::isActionChecked, mFloaterPerformance, _2, mUUIDs.front())); + LLContextMenu* menu = createFromFile("menu_avatar_rendering_settings.xml"); + + return menu; + } + + LLFloaterPerformance* mFloaterPerformance; +}; + +LLFloaterPerformance::LLFloaterPerformance(const LLSD& key) +: LLFloater(key), + mUpdateTimer(new LLTimer()), + mNearbyMaxComplexity(0) +{ + mContextMenu = new LLExceptionsContextMenu(this); +} + +LLFloaterPerformance::~LLFloaterPerformance() +{ + mMaxARTChangedSignal.disconnect(); + delete mContextMenu; + delete mUpdateTimer; +} + +BOOL LLFloaterPerformance::postBuild() +{ + mMainPanel = getChild<LLPanel>("panel_performance_main"); + mNearbyPanel = getChild<LLPanel>("panel_performance_nearby"); + mComplexityPanel = getChild<LLPanel>("panel_performance_complexity"); + mSettingsPanel = getChild<LLPanel>("panel_performance_preferences"); + mHUDsPanel = getChild<LLPanel>("panel_performance_huds"); + mAutoadjustmentsPanel = getChild<LLPanel>("panel_performance_autoadjustments"); + + getChild<LLPanel>("nearby_subpanel")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::showSelectedPanel, this, mNearbyPanel)); + getChild<LLPanel>("complexity_subpanel")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::showSelectedPanel, this, mComplexityPanel)); + getChild<LLPanel>("settings_subpanel")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::showSelectedPanel, this, mSettingsPanel)); + getChild<LLPanel>("huds_subpanel")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::showSelectedPanel, this, mHUDsPanel)); + getChild<LLPanel>("autoadjustments_subpanel")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::showSelectedPanel, this, mAutoadjustmentsPanel)); + + initBackBtn(mNearbyPanel); + initBackBtn(mComplexityPanel); + initBackBtn(mSettingsPanel); + initBackBtn(mHUDsPanel); + initBackBtn(mAutoadjustmentsPanel); + + mHUDList = mHUDsPanel->getChild<LLNameListCtrl>("hud_list"); + mHUDList->setNameListType(LLNameListCtrl::SPECIAL); + mHUDList->setHoverIconName("StopReload_Off"); + mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1)); + + mObjectList = mComplexityPanel->getChild<LLNameListCtrl>("obj_list"); + mObjectList->setNameListType(LLNameListCtrl::SPECIAL); + mObjectList->setHoverIconName("StopReload_Off"); + mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1)); + + mSettingsPanel->getChild<LLButton>("advanced_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickAdvanced, this)); + mSettingsPanel->getChild<LLRadioGroup>("graphics_quality")->setCommitCallback(boost::bind(&LLFloaterPerformance::onChangeQuality, this, _2)); + mSettingsPanel->getChild<LLCheckBoxCtrl>("advanced_lighting_model")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::onClickAdvancedLighting, this)); + mSettingsPanel->getChild<LLComboBox>("ShadowDetail")->setMouseDownCallback(boost::bind(&LLFloaterPerformance::onClickShadows, this)); + + mNearbyPanel->getChild<LLButton>("exceptions_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickExceptions, this)); + mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickHideAvatars, this)); + mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR)); + mNearbyList = mNearbyPanel->getChild<LLNameListCtrl>("nearby_list"); + mNearbyList->setRightMouseDownCallback(boost::bind(&LLFloaterPerformance::onAvatarListRightClick, this, _1, _2, _3)); + + mMaxARTChangedSignal = gSavedSettings.getControl("RenderAvatarMaxART")->getCommitSignal()->connect(boost::bind(&LLFloaterPerformance::updateMaxRenderTime, this)); + mNearbyPanel->getChild<LLSliderCtrl>("RenderAvatarMaxART")->setCommitCallback(boost::bind(&LLFloaterPerformance::updateMaxRenderTime, this)); + + // store the current setting as the users desired reflection detail and DD + gSavedSettings.setS32("UserTargetReflections", LLPipeline::RenderReflectionDetail); + if(!LLPerfStats::tunables.userAutoTuneEnabled) + { + gSavedSettings.setF32("AutoTuneRenderFarClipTarget", LLPipeline::RenderFarClip); + } + + return TRUE; +} + +void LLFloaterPerformance::showSelectedPanel(LLPanel* selected_panel) +{ + hidePanels(); + mMainPanel->setVisible(FALSE); + selected_panel->setVisible(TRUE); + + if (mHUDsPanel == selected_panel) + { + populateHUDList(); + } + else if (mNearbyPanel == selected_panel) + { + populateNearbyList(); + } + else if (mComplexityPanel == selected_panel) + { + populateObjectList(); + } +} + +void LLFloaterPerformance::showAutoadjustmentsPanel() +{ + showSelectedPanel(mAutoadjustmentsPanel); +} + +void LLFloaterPerformance::draw() +{ + if (mUpdateTimer->hasExpired()) + { + setFPSText(); + if (mHUDsPanel->getVisible()) + { + populateHUDList(); + } + else if (mNearbyPanel->getVisible()) + { + populateNearbyList(); + mNearbyPanel->getChild<LLCheckBoxCtrl>("hide_avatars")->set(!LLPipeline::hasRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR)); + } + else if (mComplexityPanel->getVisible()) + { + populateObjectList(); + } + + auto button = getChild<LLButton>("AutoTuneFPS"); + if((bool)button->getToggleState() != LLPerfStats::tunables.userAutoTuneEnabled) + { + button->toggleState(); + } + + mUpdateTimer->setTimerExpirySec(REFRESH_INTERVAL); + } + LLFloater::draw(); +} + +void LLFloaterPerformance::showMainPanel() +{ + hidePanels(); + mMainPanel->setVisible(TRUE); +} + +void LLFloaterPerformance::hidePanels() +{ + mNearbyPanel->setVisible(FALSE); + mComplexityPanel->setVisible(FALSE); + mHUDsPanel->setVisible(FALSE); + mSettingsPanel->setVisible(FALSE); + mAutoadjustmentsPanel->setVisible(FALSE); +} + +void LLFloaterPerformance::initBackBtn(LLPanel* panel) +{ + panel->getChild<LLButton>("back_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::showMainPanel, this)); + + panel->getChild<LLTextBox>("back_lbl")->setShowCursorHand(false); + panel->getChild<LLTextBox>("back_lbl")->setSoundFlags(LLView::MOUSE_UP); + panel->getChild<LLTextBox>("back_lbl")->setClickedCallback(boost::bind(&LLFloaterPerformance::showMainPanel, this)); +} + +void LLFloaterPerformance::populateHUDList() +{ + S32 prev_pos = mHUDList->getScrollPos(); + LLUUID prev_selected_id = mHUDList->getSelectedSpecialId(); + mHUDList->clearRows(); + mHUDList->updateColumns(true); + + hud_complexity_list_t complexity_list = LLHUDRenderNotifier::getInstance()->getHUDComplexityList(); + + hud_complexity_list_t::iterator iter = complexity_list.begin(); + hud_complexity_list_t::iterator end = complexity_list.end(); + + auto huds_max_render_time_raw = LLPerfStats::StatsRecorder::getMax(HudType, LLPerfStats::StatType_t::RENDER_GEOMETRY); + for (iter = complexity_list.begin(); iter != end; ++iter) + { + LLHUDComplexity hud_object_complexity = *iter; + + auto hud_render_time_raw = LLPerfStats::StatsRecorder::get(HudType, hud_object_complexity.objectId, LLPerfStats::StatType_t::RENDER_GEOMETRY); + + LLSD item; + item["special_id"] = hud_object_complexity.objectId; + item["target"] = LLNameListCtrl::SPECIAL; + LLSD& row = item["columns"]; + row[0]["column"] = "complex_visual"; + row[0]["type"] = "bar"; + LLSD& value = row[0]["value"]; + value["ratio"] = (F32)hud_render_time_raw / huds_max_render_time_raw; + value["bottom"] = BAR_BOTTOM_PAD; + value["left_pad"] = BAR_LEFT_PAD; + value["right_pad"] = BAR_RIGHT_PAD; + + row[1]["column"] = "complex_value"; + row[1]["type"] = "text"; + row[1]["value"] = llformat( "%.f",LLPerfStats::raw_to_us(hud_render_time_raw) ); + row[1]["font"]["name"] = "SANSSERIF"; + + row[2]["column"] = "name"; + row[2]["type"] = "text"; + row[2]["value"] = hud_object_complexity.objectName; + row[2]["font"]["name"] = "SANSSERIF"; + + LLScrollListItem* obj = mHUDList->addElement(item); + if (obj) + { + LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(obj->getColumn(1)); + if (value_text) + { + value_text->setAlignment(LLFontGL::HCENTER); + } + } + } + mHUDList->sortByColumnIndex(1, FALSE); + mHUDList->setScrollPos(prev_pos); + mHUDList->selectItemBySpecialId(prev_selected_id); +} + +void LLFloaterPerformance::populateObjectList() +{ + S32 prev_pos = mObjectList->getScrollPos(); + LLUUID prev_selected_id = mObjectList->getSelectedSpecialId(); + mObjectList->clearRows(); + mObjectList->updateColumns(true); + + object_complexity_list_t complexity_list = LLAvatarRenderNotifier::getInstance()->getObjectComplexityList(); + + object_complexity_list_t::iterator iter = complexity_list.begin(); + object_complexity_list_t::iterator end = complexity_list.end(); + + // for consistency we lock the buffer while we build the list. In theory this is uncontended as the buffer should only toggle on end of frame + { + std::lock_guard<std::mutex> guard{ LLPerfStats::bufferToggleLock }; + auto att_max_render_time_raw = LLPerfStats::StatsRecorder::getMax(AttType, LLPerfStats::StatType_t::RENDER_COMBINED); + + for (iter = complexity_list.begin(); iter != end; ++iter) + { + LLObjectComplexity object_complexity = *iter; + + auto attach_render_time_raw = LLPerfStats::StatsRecorder::get(AttType, object_complexity.objectId, LLPerfStats::StatType_t::RENDER_COMBINED); + LLSD item; + item["special_id"] = object_complexity.objectId; + item["target"] = LLNameListCtrl::SPECIAL; + LLSD& row = item["columns"]; + row[0]["column"] = "complex_visual"; + row[0]["type"] = "bar"; + LLSD& value = row[0]["value"]; + value["ratio"] = ((F32)attach_render_time_raw) / att_max_render_time_raw; + value["bottom"] = BAR_BOTTOM_PAD; + value["left_pad"] = BAR_LEFT_PAD; + value["right_pad"] = BAR_RIGHT_PAD; + + row[1]["column"] = "complex_value"; + row[1]["type"] = "text"; + row[1]["value"] = llformat("%.f", LLPerfStats::raw_to_us(attach_render_time_raw)); + row[1]["font"]["name"] = "SANSSERIF"; + + row[2]["column"] = "name"; + row[2]["type"] = "text"; + row[2]["value"] = object_complexity.objectName; + row[2]["font"]["name"] = "SANSSERIF"; + + LLScrollListItem* obj = mObjectList->addElement(item); + if (obj) + { + LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(obj->getColumn(1)); + if (value_text) + { + value_text->setAlignment(LLFontGL::HCENTER); + } + } + } + } + mObjectList->sortByColumnIndex(1, FALSE); + mObjectList->setScrollPos(prev_pos); + mObjectList->selectItemBySpecialId(prev_selected_id); +} + +void LLFloaterPerformance::populateNearbyList() +{ + static LLCachedControl<bool> showTunedART(gSavedSettings, "ShowTunedART"); + S32 prev_pos = mNearbyList->getScrollPos(); + LLUUID prev_selected_id = mNearbyList->getStringUUIDSelectedItem(); + mNearbyList->clearRows(); + mNearbyList->updateColumns(true); + + static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0); + std::vector<LLCharacter*> valid_nearby_avs; + mNearbyMaxComplexity = LLWorld::getInstance()->getNearbyAvatarsAndCompl(valid_nearby_avs); + + std::vector<LLCharacter*>::iterator char_iter = valid_nearby_avs.begin(); + + LLPerfStats::bufferToggleLock.lock(); + auto av_render_max_raw = LLPerfStats::StatsRecorder::getMax(AvType, LLPerfStats::StatType_t::RENDER_COMBINED); + LLPerfStats::bufferToggleLock.unlock(); + + while (char_iter != valid_nearby_avs.end()) + { + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter); + if (avatar && (LLVOAvatar::AOA_INVISIBLE != avatar->getOverallAppearance())) + { + LLPerfStats::bufferToggleLock.lock(); + auto render_av_raw = LLPerfStats::StatsRecorder::get(AvType, avatar->getID(),LLPerfStats::StatType_t::RENDER_COMBINED); + LLPerfStats::bufferToggleLock.unlock(); + + auto is_slow = avatar->isTooSlowWithShadows(); + LLSD item; + item["id"] = avatar->getID(); + LLSD& row = item["columns"]; + row[0]["column"] = "complex_visual"; + row[0]["type"] = "bar"; + LLSD& value = row[0]["value"]; + // The ratio used in the bar is the current cost, as soon as we take action this changes so we keep the + // pre-tune value for the numerical column and sorting. + value["ratio"] = (double)render_av_raw / av_render_max_raw; + value["bottom"] = BAR_BOTTOM_PAD; + value["left_pad"] = BAR_LEFT_PAD; + value["right_pad"] = BAR_RIGHT_PAD; + + row[1]["column"] = "complex_value"; + row[1]["type"] = "text"; + if (is_slow && !showTunedART) + { + row[1]["value"] = llformat( "%.f", LLPerfStats::raw_to_us( avatar->getLastART() ) ); + } + else + { + row[1]["value"] = llformat( "%.f", LLPerfStats::raw_to_us( render_av_raw ) ); + } + row[1]["font"]["name"] = "SANSSERIF"; + + row[2]["column"] = "name"; + row[2]["type"] = "text"; + row[2]["value"] = avatar->getFullname(); + row[2]["font"]["name"] = "SANSSERIF"; + + LLScrollListItem* av_item = mNearbyList->addElement(item); + if(av_item) + { + LLScrollListText* value_text = dynamic_cast<LLScrollListText*>(av_item->getColumn(1)); + if (value_text) + { + value_text->setAlignment(LLFontGL::HCENTER); + } + LLScrollListText* name_text = dynamic_cast<LLScrollListText*>(av_item->getColumn(2)); + if (name_text) + { + if (avatar->isSelf()) + { + name_text->setColor(LLUIColorTable::instance().getColor("DrYellow")); + } + else + { + std::string color = "white"; + if (is_slow || LLVOAvatar::AOA_JELLYDOLL == avatar->getOverallAppearance()) + { + color = "LabelDisabledColor"; + LLScrollListBar* bar = dynamic_cast<LLScrollListBar*>(av_item->getColumn(0)); + if (bar) + { + bar->setColor(LLUIColorTable::instance().getColor(color)); + } + } + else if (LLVOAvatar::AOA_NORMAL == avatar->getOverallAppearance()) + { + color = LLAvatarActions::isFriend(avatar->getID()) ? "ConversationFriendColor" : "white"; + } + name_text->setColor(LLUIColorTable::instance().getColor(color)); + } + } + } + } + char_iter++; + } + mNearbyList->sortByColumnIndex(1, FALSE); + mNearbyList->setScrollPos(prev_pos); + mNearbyList->selectByID(prev_selected_id); +} + +void LLFloaterPerformance::setFPSText() +{ + const S32 NUM_PERIODS = 50; + S32 current_fps = (S32)llround(LLTrace::get_frame_recording().getPeriodMedianPerSec(LLStatViewer::FPS, NUM_PERIODS)); + getChild<LLTextBox>("fps_value")->setValue(current_fps); + + std::string fps_text = getString("fps_text"); + static LLCachedControl<bool> vsync_enabled(gSavedSettings, "RenderVSyncEnable", true); + S32 refresh_rate = gViewerWindow->getWindow()->getRefreshRate(); + if (vsync_enabled && (refresh_rate > 0) && (current_fps >= refresh_rate)) + { + fps_text += getString("max_text"); + } + getChild<LLTextBox>("fps_lbl")->setValue(fps_text); +} + +void LLFloaterPerformance::detachItem(const LLUUID& item_id) +{ + LLAppearanceMgr::instance().removeItemFromAvatar(item_id); +} + +void LLFloaterPerformance::onClickAdvanced() +{ + LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->saveSettings(); + } + LLFloaterReg::showInstance("prefs_graphics_advanced"); +} + +void LLFloaterPerformance::onChangeQuality(const LLSD& data) +{ + LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->onChangeQuality(data); + } +} + +void LLFloaterPerformance::onClickHideAvatars() +{ + LLPipeline::toggleRenderTypeControl(LLPipeline::RENDER_TYPE_AVATAR); +} + +void LLFloaterPerformance::onClickExceptions() +{ + LLFloaterReg::showInstance("avatar_render_settings"); +} + +void LLFloaterPerformance::updateMaxRenderTime() +{ + LLAvatarComplexityControls::updateMaxRenderTime( + mNearbyPanel->getChild<LLSliderCtrl>("RenderAvatarMaxART"), + mNearbyPanel->getChild<LLTextBox>("RenderAvatarMaxARTText"), + true); +} + +static LLVOAvatar* find_avatar(const LLUUID& id) +{ + LLViewerObject *obj = gObjectList.findObject(id); + while (obj && obj->isAttachment()) + { + obj = (LLViewerObject *)obj->getParent(); + } + + if (obj && obj->isAvatar()) + { + return (LLVOAvatar*)obj; + } + else + { + return NULL; + } +} + +void LLFloaterPerformance::onCustomAction(const LLSD& userdata, const LLUUID& av_id) +{ + const std::string command_name = userdata.asString(); + + S32 new_setting = 0; + if ("default" == command_name) + { + new_setting = S32(LLVOAvatar::AV_RENDER_NORMALLY); + } + else if ("never" == command_name) + { + new_setting = S32(LLVOAvatar::AV_DO_NOT_RENDER); + } + else if ("always" == command_name) + { + new_setting = S32(LLVOAvatar::AV_ALWAYS_RENDER); + } + + LLVOAvatar *avatarp = find_avatar(av_id); + if (avatarp) + { + avatarp->setVisualMuteSettings(LLVOAvatar::VisualMuteSettings(new_setting)); + } + else + { + LLRenderMuteList::getInstance()->saveVisualMuteSetting(av_id, new_setting); + } +} + + +bool LLFloaterPerformance::isActionChecked(const LLSD& userdata, const LLUUID& av_id) +{ + const std::string command_name = userdata.asString(); + + S32 visual_setting = LLRenderMuteList::getInstance()->getSavedVisualMuteSetting(av_id); + if ("default" == command_name) + { + return (visual_setting == S32(LLVOAvatar::AV_RENDER_NORMALLY)); + } + else if ("non_default" == command_name) + { + return (visual_setting != S32(LLVOAvatar::AV_RENDER_NORMALLY)); + } + else if ("never" == command_name) + { + return (visual_setting == S32(LLVOAvatar::AV_DO_NOT_RENDER)); + } + else if ("always" == command_name) + { + return (visual_setting == S32(LLVOAvatar::AV_ALWAYS_RENDER)); + } + return false; +} + +void LLFloaterPerformance::onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y) +{ + LLNameListCtrl* list = dynamic_cast<LLNameListCtrl*>(ctrl); + if (!list) return; + list->selectItemAt(x, y, MASK_NONE); + uuid_vec_t selected_uuids; + + if((list->getCurrentID().notNull()) && (list->getCurrentID() != gAgentID)) + { + selected_uuids.push_back(list->getCurrentID()); + mContextMenu->show(ctrl, selected_uuids, x, y); + } +} + +const U32 RENDER_QUALITY_LEVEL = 3; +void LLFloaterPerformance::changeQualityLevel(const std::string& notif) +{ + LLNotificationsUtil::add(notif, LLSD(), LLSD(), + [](const LLSD¬if, const LLSD&resp) + { + S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp); + if (opt == 0) + { + LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + gSavedSettings.setU32("RenderQualityPerformance", RENDER_QUALITY_LEVEL); + instance->onChangeQuality(LLSD((S32)RENDER_QUALITY_LEVEL)); + } + } + }); +} + +bool is_ALM_available() +{ + bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump"); + bool shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); + + return LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + bumpshiny && + shaders; +} + +void LLFloaterPerformance::onClickAdvancedLighting() +{ + if (!is_ALM_available()) + { + changeQualityLevel("AdvancedLightingConfirm"); + } +} + +void LLFloaterPerformance::onClickShadows() +{ + if (!is_ALM_available() || !gSavedSettings.getBOOL("RenderDeferred")) + { + changeQualityLevel("ShadowsConfirm"); + } + +} +// EOF diff --git a/indra/newview/llfloaterperformance.h b/indra/newview/llfloaterperformance.h new file mode 100644 index 0000000000..09bcd18bb5 --- /dev/null +++ b/indra/newview/llfloaterperformance.h @@ -0,0 +1,93 @@ +/** + * @file llfloaterperformance.h + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERPERFORMANCE_H +#define LL_LLFLOATERPERFORMANCE_H + +#include "llfloater.h" +#include "lllistcontextmenu.h" + +class LLCharacter; +class LLNameListCtrl; + +class LLFloaterPerformance : public LLFloater +{ +public: + LLFloaterPerformance(const LLSD& key); + virtual ~LLFloaterPerformance(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + + void showSelectedPanel(LLPanel* selected_panel); + void showMainPanel(); + void hidePanels(); + void showAutoadjustmentsPanel(); + + void detachItem(const LLUUID& item_id); + + void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + + void onCustomAction (const LLSD& userdata, const LLUUID& av_id); + bool isActionChecked(const LLSD& userdata, const LLUUID& av_id); + +private: + void initBackBtn(LLPanel* panel); + void populateHUDList(); + void populateObjectList(); + void populateNearbyList(); + void setFPSText(); + + void onClickAdvanced(); + void onChangeQuality(const LLSD& data); + void onClickHideAvatars(); + void onClickExceptions(); + void onClickShadows(); + void onClickAdvancedLighting(); + + void updateMaxRenderTime(); + + static void changeQualityLevel(const std::string& notif); + + LLPanel* mMainPanel; + LLPanel* mNearbyPanel; + LLPanel* mComplexityPanel; + LLPanel* mHUDsPanel; + LLPanel* mSettingsPanel; + LLPanel* mAutoadjustmentsPanel; + LLNameListCtrl* mHUDList; + LLNameListCtrl* mObjectList; + LLNameListCtrl* mNearbyList; + + LLListContextMenu* mContextMenu; + + LLTimer* mUpdateTimer; + + S32 mNearbyMaxComplexity; + + boost::signals2::connection mMaxARTChangedSignal; +}; + +#endif // LL_LLFLOATERPERFORMANCE_H diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 273810e8d4..77c269a296 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -50,6 +50,8 @@ #include "llfloaterreg.h" #include "llfloaterabout.h" #include "llfavoritesbar.h" +#include "llfloaterpreferencesgraphicsadvanced.h" +#include "llfloaterperformance.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterimsession.h" #include "llkeyboard.h" @@ -74,7 +76,6 @@ #include "llviewereventrecorder.h" #include "llviewermessage.h" #include "llviewerwindow.h" -#include "llviewershadermgr.h" #include "llviewerthrottle.h" #include "llvoavatarself.h" #include "llvotree.h" @@ -98,11 +99,9 @@ #include "lltextbox.h" #include "llui.h" #include "llviewerobjectlist.h" -#include "llvoavatar.h" #include "llvovolume.h" #include "llwindow.h" #include "llworld.h" -#include "pipeline.h" #include "lluictrlfactory.h" #include "llviewermedia.h" #include "llpluginclassmedia.h" @@ -115,10 +114,9 @@ #include "llpresetsmanager.h" #include "llviewercontrol.h" #include "llpresetsmanager.h" -#include "llfeaturemanager.h" -#include "llviewertexturelist.h" #include "llsearchableui.h" +#include "llperfstats.h" const F32 BANDWIDTH_UPDATER_TIMEOUT = 0.5f; char const* const VISIBILITY_DEFAULT = "default"; @@ -290,6 +288,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this)); mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this)); mCommitCallbackRegistrar.add("Pref.RenderExceptions", boost::bind(&LLFloaterPreference::onClickRenderExceptions, this)); + mCommitCallbackRegistrar.add("Pref.AutoAdjustments", boost::bind(&LLFloaterPreference::onClickAutoAdjustments, this)); mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this)); mCommitCallbackRegistrar.add("Pref.AvatarImpostorsEnable", boost::bind(&LLFloaterPreference::onAvatarImpostorsEnable, this)); mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreference::updateMaxComplexity, this)); @@ -321,6 +320,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); + mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreference::updateComplexityText, this)); + mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering @@ -487,6 +488,7 @@ void LLFloaterPreference::onDoNotDisturbResponseChanged() LLFloaterPreference::~LLFloaterPreference() { LLConversationLog::instance().removeObserver(this); + mComplexityChangedSignal.disconnect(); } void LLFloaterPreference::draw() @@ -726,13 +728,15 @@ void LLFloaterPreference::onOpen(const LLSD& key) LLButton* save_btn = findChild<LLButton>("PrefSaveButton"); LLButton* delete_btn = findChild<LLButton>("PrefDeleteButton"); LLButton* exceptions_btn = findChild<LLButton>("RenderExceptionsButton"); + LLButton* auto_adjustments_btn = findChild<LLButton>("AutoAdjustmentsButton"); - if (load_btn && save_btn && delete_btn && exceptions_btn) + if (load_btn && save_btn && delete_btn && exceptions_btn && auto_adjustments_btn) { load_btn->setEnabled(started); save_btn->setEnabled(started); delete_btn->setEnabled(started); exceptions_btn->setEnabled(started); + auto_adjustments_btn->setEnabled(started); } collectSearchableItems(); @@ -748,33 +752,6 @@ void LLFloaterPreference::onRenderOptionEnable() refreshEnabledGraphics(); } -void LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable() -{ - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) - { - instance->refresh(); - } - - refreshEnabledGraphics(); -} - -void LLFloaterPreferenceGraphicsAdvanced::onAdvancedAtmosphericsEnable() -{ - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) - { - instance->refresh(); - } - - refreshEnabledGraphics(); -} - -void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledGraphics() -{ - refreshEnabledState(); -} - void LLFloaterPreference::onAvatarImpostorsEnable() { refreshEnabledGraphics(); @@ -1209,98 +1186,6 @@ void LLFloaterPreference::refreshEnabledState() getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess()); } -void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() -{ - LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); - LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); - - // Reflections - BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps; - ctrl_reflections->setEnabled(reflections); - reflections_text->setEnabled(reflections); - - // Bump & Shiny - LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny"); - bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); - bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE); - - // Avatar Mode - // Avatar Render Mode - getChild<LLCheckBoxCtrl>("AvatarCloth")->setEnabled(TRUE); - - // Vertex Shaders, Global Shader Enable - // SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code - LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail"); // can be linked with control var - LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText"); - - terrain_detail->setEnabled(FALSE); - terrain_text->setEnabled(FALSE); - - // WindLight - LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); - LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail"); - LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText"); - ctrl_wind_light->setEnabled(TRUE); - sky->setEnabled(TRUE); - sky_text->setEnabled(TRUE); - - //Deferred/SSAO/Shadows - LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); - - BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && - ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && - (ctrl_wind_light->get()) ? TRUE : FALSE; - - ctrl_deferred->setEnabled(enabled); - - LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); - LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); - LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail"); - LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText"); - - // note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it - enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE); - - ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred")); - - ctrl_ssao->setEnabled(enabled); - ctrl_dof->setEnabled(enabled); - - enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"); - - ctrl_shadow->setEnabled(enabled); - shadow_text->setEnabled(enabled); - - // Hardware settings - F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); - S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); - S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); - getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value()); - getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); - - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || - !gGLManager.mHasVertexBufferObject) - { - getChildView("vbo")->setEnabled(FALSE); - } - - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") || - !gGLManager.mHasVertexBufferObject) - { - getChildView("texture compression")->setEnabled(FALSE); - } - - // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance - LLUICtrl* gamma_ctrl = getChild<LLUICtrl>("gamma"); - gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders()); - getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders()); - getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders()); - getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred")); - - // now turn off any features that are unavailable - disableUnavailableSettings(); -} - // static void LLAvatarComplexityControls::setIndirectControls() { @@ -1343,92 +1228,6 @@ void LLAvatarComplexityControls::setIndirectMaxArc() gSavedSettings.setU32("IndirectMaxComplexity", indirect_max_arc); } -void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings() -{ - LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); - LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); - LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth"); - LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); - LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); - LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail"); - LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText"); - LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); - LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); - LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail"); - LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText"); - - // disabled windlight - if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) - { - ctrl_wind_light->setEnabled(FALSE); - ctrl_wind_light->setValue(FALSE); - - sky->setEnabled(FALSE); - sky_text->setEnabled(FALSE); - - //deferred needs windlight, disable deferred - ctrl_shadows->setEnabled(FALSE); - ctrl_shadows->setValue(0); - shadows_text->setEnabled(FALSE); - - ctrl_ssao->setEnabled(FALSE); - ctrl_ssao->setValue(FALSE); - - ctrl_dof->setEnabled(FALSE); - ctrl_dof->setValue(FALSE); - - ctrl_deferred->setEnabled(FALSE); - ctrl_deferred->setValue(FALSE); - } - - // disabled deferred - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred")) - { - ctrl_shadows->setEnabled(FALSE); - ctrl_shadows->setValue(0); - shadows_text->setEnabled(FALSE); - - ctrl_ssao->setEnabled(FALSE); - ctrl_ssao->setValue(FALSE); - - ctrl_dof->setEnabled(FALSE); - ctrl_dof->setValue(FALSE); - - ctrl_deferred->setEnabled(FALSE); - ctrl_deferred->setValue(FALSE); - } - - // disabled deferred SSAO - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) - { - ctrl_ssao->setEnabled(FALSE); - ctrl_ssao->setValue(FALSE); - } - - // disabled deferred shadows - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) - { - ctrl_shadows->setEnabled(FALSE); - ctrl_shadows->setValue(0); - shadows_text->setEnabled(FALSE); - } - - // disabled reflections - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) - { - ctrl_reflections->setEnabled(FALSE); - ctrl_reflections->setValue(FALSE); - reflections_text->setEnabled(FALSE); - } - - // disabled cloth - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) - { - ctrl_avatar_cloth->setEnabled(FALSE); - ctrl_avatar_cloth->setValue(FALSE); - } -} - void LLFloaterPreference::refresh() { LLPanel::refresh(); @@ -1444,32 +1243,6 @@ void LLFloaterPreference::refresh() updateClickActionViews(); } -void LLFloaterPreferenceGraphicsAdvanced::refresh() -{ - getChild<LLUICtrl>("fsaa")->setValue((LLSD::Integer) gSavedSettings.getU32("RenderFSAASamples")); - - // sliders and their text boxes - // mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow"); - // slider text boxes - updateSliderText(getChild<LLSliderCtrl>("ObjectMeshDetail", true), getChild<LLTextBox>("ObjectMeshDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail", true), getChild<LLTextBox>("FlexibleMeshDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail", true), getChild<LLTextBox>("TreeMeshDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail", true), getChild<LLTextBox>("AvatarMeshDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail", true), getChild<LLTextBox>("AvatarPhysicsDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true)); - updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true)); - updateSliderText(getChild<LLSliderCtrl>("TerrainDetail", true), getChild<LLTextBox>("TerrainDetailText", true)); - LLAvatarComplexityControls::setIndirectControls(); - setMaxNonImpostorsText( - gSavedSettings.getU32("RenderAvatarMaxNonImpostors"), - getChild<LLTextBox>("IndirectMaxNonImpostorsText", true)); - LLAvatarComplexityControls::setText( - gSavedSettings.getU32("RenderAvatarMaxComplexity"), - getChild<LLTextBox>("IndirectMaxComplexityText", true)); - refreshEnabledState(); -} - void LLFloaterPreference::onCommitWindowedMode() { refresh(); @@ -1673,64 +1446,7 @@ void LLFloaterPreference::refreshUI() refresh(); } -void LLFloaterPreferenceGraphicsAdvanced::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box) -{ - if (text_box == NULL || ctrl== NULL) - return; - - // get range and points when text should change - F32 value = (F32)ctrl->getValue().asReal(); - F32 min = ctrl->getMinValue(); - F32 max = ctrl->getMaxValue(); - F32 range = max - min; - llassert(range > 0); - F32 midPoint = min + range / 3.0f; - F32 highPoint = min + (2.0f * range / 3.0f); - - // choose the right text - if (value < midPoint) - { - text_box->setText(LLTrans::getString("GraphicsQualityLow")); - } - else if (value < highPoint) - { - text_box->setText(LLTrans::getString("GraphicsQualityMid")); - } - else - { - text_box->setText(LLTrans::getString("GraphicsQualityHigh")); - } -} - -void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors() -{ - // Called when the IndirectMaxNonImpostors control changes - // Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors - LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors",true); - U32 value = ctrl->getValue().asInteger(); - - if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value) - { - value=0; - } - gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value); - LLVOAvatar::updateImpostorRendering(value); // make it effective immediately - setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); -} - -void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box) -{ - if (0 == value) - { - text_box->setText(LLTrans::getString("no_limit")); - } - else - { - text_box->setText(llformat("%d", value)); - } -} - -void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* value_label) +void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val) { // Called when the IndirectMaxComplexity control changes // Responsible for fixing the slider label (IndirectMaxComplexityText) and setting RenderAvatarMaxComplexity @@ -1752,10 +1468,10 @@ void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* valu } gSavedSettings.setU32("RenderAvatarMaxComplexity", (U32)max_arc); - setText(max_arc, value_label); + setText(max_arc, value_label, short_val); } -void LLAvatarComplexityControls::setText(U32 value, LLTextBox* text_box) +void LLAvatarComplexityControls::setText(U32 value, LLTextBox* text_box, bool short_val) { if (0 == value) { @@ -1763,24 +1479,40 @@ void LLAvatarComplexityControls::setText(U32 value, LLTextBox* text_box) } else { - text_box->setText(llformat("%d", value)); + std::string text_value = short_val ? llformat("%d", value / 1000) : llformat("%d", value); + text_box->setText(text_value); } } +void LLAvatarComplexityControls::updateMaxRenderTime(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val) +{ + setRenderTimeText((F32)(LLPerfStats::renderAvatarMaxART_ns/1000), value_label, short_val); +} + +void LLAvatarComplexityControls::setRenderTimeText(F32 value, LLTextBox* text_box, bool short_val) +{ + if (0 == value) + { + text_box->setText(LLTrans::getString("no_limit")); + } + else + { + text_box->setText(llformat("%.0f", value)); + } +} + void LLFloaterPreference::updateMaxComplexity() { // Called when the IndirectMaxComplexity control changes LLAvatarComplexityControls::updateMax( getChild<LLSliderCtrl>("IndirectMaxComplexity"), getChild<LLTextBox>("IndirectMaxComplexityText")); +} - LLFloaterPreferenceGraphicsAdvanced* floater_graphics_advanced = LLFloaterReg::findTypedInstance<LLFloaterPreferenceGraphicsAdvanced>("prefs_graphics_advanced"); - if (floater_graphics_advanced) - { - LLAvatarComplexityControls::updateMax( - floater_graphics_advanced->getChild<LLSliderCtrl>("IndirectMaxComplexity"), - floater_graphics_advanced->getChild<LLTextBox>("IndirectMaxComplexityText")); - } +void LLFloaterPreference::updateComplexityText() +{ + LLAvatarComplexityControls::setText(gSavedSettings.getU32("RenderAvatarMaxComplexity"), + getChild<LLTextBox>("IndirectMaxComplexityText", true)); } bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map) @@ -1822,22 +1554,6 @@ bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map return true; } -void LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity() -{ - // Called when the IndirectMaxComplexity control changes - LLAvatarComplexityControls::updateMax( - getChild<LLSliderCtrl>("IndirectMaxComplexity"), - getChild<LLTextBox>("IndirectMaxComplexityText")); - - LLFloaterPreference* floater_preferences = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (floater_preferences) - { - LLAvatarComplexityControls::updateMax( - floater_preferences->getChild<LLSliderCtrl>("IndirectMaxComplexity"), - floater_preferences->getChild<LLTextBox>("IndirectMaxComplexityText")); - } -} - void LLFloaterPreference::onChangeMaturity() { U8 sim_access = gSavedSettings.getU32("PreferredMaturity"); @@ -1942,6 +1658,15 @@ void LLFloaterPreference::onClickRenderExceptions() LLFloaterReg::showInstance("avatar_render_settings"); } +void LLFloaterPreference::onClickAutoAdjustments() +{ + LLFloaterPerformance* performance_floater = LLFloaterReg::showTypedInstance<LLFloaterPerformance>("performance"); + if (performance_floater) + { + performance_floater->showAutoadjustmentsPanel(); + } +} + void LLFloaterPreference::onClickAdvanced() { LLFloaterReg::showInstance("prefs_graphics_advanced"); @@ -3284,18 +3009,6 @@ void LLPanelPreferenceControls::onCancelKeyBind() pControlsTable->deselectAllItems(); } -LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key) - : LLFloater(key) -{ - mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable, this)); - mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors,this)); - mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity,this)); -} - -LLFloaterPreferenceGraphicsAdvanced::~LLFloaterPreferenceGraphicsAdvanced() -{ -} - LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) : LLFloater(key), mSocksSettingsDirty(false) @@ -3305,41 +3018,6 @@ LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); } -BOOL LLFloaterPreferenceGraphicsAdvanced::postBuild() -{ - // Don't do this on Mac as their braindead GL versioning - // sets this when 8x and 16x are indeed available - // -#if !LL_DARWIN - if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f) - { //remove FSAA settings above "4x" - LLComboBox* combo = getChild<LLComboBox>("fsaa"); - combo->remove("8x"); - combo->remove("16x"); - } - - LLCheckBoxCtrl *use_HiDPI = getChild<LLCheckBoxCtrl>("use HiDPI"); - use_HiDPI->setVisible(FALSE); -#endif - - return TRUE; -} - -void LLFloaterPreferenceGraphicsAdvanced::onOpen(const LLSD& key) -{ - refresh(); -} - -void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting) -{ - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) - { - instance->cancel(); - } - updateMaxComplexity(); -} - LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy() { } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 542df18ddb..1079b41000 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -109,9 +109,10 @@ public: void updateClickActionViews(); void updateSearchableItems(); + void onBtnOK(const LLSD& userdata); + void onBtnCancel(const LLSD& userdata); + protected: - void onBtnOK(const LLSD& userdata); - void onBtnCancel(const LLSD& userdata); void onClickClearCache(); // Clear viewer texture cache, file cache on next startup void onClickBrowserClearCache(); // Clear web history and caches as well as viewer caches above @@ -184,6 +185,7 @@ public: void onClickAutoReplace(); void onClickSpellChecker(); void onClickRenderExceptions(); + void onClickAutoAdjustments(); void onClickAdvanced(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); @@ -200,6 +202,7 @@ private: void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response); void updateDeleteTranscriptsButton(); void updateMaxComplexity(); + void updateComplexityText(); static bool loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map); static std::string sSkin; @@ -221,6 +224,8 @@ private: std::unique_ptr< ll::prefs::SearchData > mSearchData; bool mSearchDataDirty; + boost::signals2::connection mComplexityChangedSignal; + void onUpdateFilterTerm( bool force = false ); void collectSearchableItems(); }; @@ -347,37 +352,13 @@ private: S32 mEditingMode; }; -class LLFloaterPreferenceGraphicsAdvanced : public LLFloater -{ - public: - LLFloaterPreferenceGraphicsAdvanced(const LLSD& key); - ~LLFloaterPreferenceGraphicsAdvanced(); - /*virtual*/ BOOL postBuild(); - void onOpen(const LLSD& key); - void onClickCloseBtn(bool app_quitting); - void disableUnavailableSettings(); - void refreshEnabledGraphics(); - void refreshEnabledState(); - void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box); - void updateMaxNonImpostors(); - void setMaxNonImpostorsText(U32 value, LLTextBox* text_box); - void updateMaxComplexity(); - void setMaxComplexityText(U32 value, LLTextBox* text_box); - static void setIndirectControls(); - static void setIndirectMaxNonImpostors(); - static void setIndirectMaxArc(); - void refresh(); - // callback for when client modifies a render option - void onRenderOptionEnable(); - void onAdvancedAtmosphericsEnable(); - LOG_CLASS(LLFloaterPreferenceGraphicsAdvanced); -}; - class LLAvatarComplexityControls { public: - static void updateMax(LLSliderCtrl* slider, LLTextBox* value_label); - static void setText(U32 value, LLTextBox* text_box); + static void updateMax(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val = false); + static void setText(U32 value, LLTextBox* text_box, bool short_val = false); + static void updateMaxRenderTime(LLSliderCtrl* slider, LLTextBox* value_label, bool short_val = false); + static void setRenderTimeText(F32 value, LLTextBox* text_box, bool short_val = false); static void setIndirectControls(); static void setIndirectMaxNonImpostors(); static void setIndirectMaxArc(); diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp new file mode 100644 index 0000000000..98ebe7d4e8 --- /dev/null +++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp @@ -0,0 +1,473 @@ +/** + * @file llfloaterpreferencesgraphicsadvanced.cpp + * @brief floater for adjusting camera position + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterpreferencesgraphicsadvanced.h" + +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llfeaturemanager.h" +#include "llfloaterpreference.h" +#include "llfloaterreg.h" +#include "llnotificationsutil.h" +#include "llsliderctrl.h" +#include "lltextbox.h" +#include "lltrans.h" +#include "llviewershadermgr.h" +#include "llviewertexturelist.h" +#include "llvoavatar.h" +#include "pipeline.h" + + +LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key) + : LLFloater(key) +{ + mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable, this)); + mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors,this)); + mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity,this)); + + mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnCancel, this, _2)); + mCommitCallbackRegistrar.add("Pref.OK", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnOK, this, _2)); + + gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors, this, _2)); +} + +LLFloaterPreferenceGraphicsAdvanced::~LLFloaterPreferenceGraphicsAdvanced() +{ + mComplexityChangedSignal.disconnect(); +} + +BOOL LLFloaterPreferenceGraphicsAdvanced::postBuild() +{ + // Don't do this on Mac as their braindead GL versioning + // sets this when 8x and 16x are indeed available + // +#if !LL_DARWIN + if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f) + { //remove FSAA settings above "4x" + LLComboBox* combo = getChild<LLComboBox>("fsaa"); + combo->remove("8x"); + combo->remove("16x"); + } + + LLCheckBoxCtrl *use_HiDPI = getChild<LLCheckBoxCtrl>("use HiDPI"); + use_HiDPI->setVisible(FALSE); +#endif + + mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateComplexityText, this)); + + return TRUE; +} + +void LLFloaterPreferenceGraphicsAdvanced::onOpen(const LLSD& key) +{ + refresh(); +} + +void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting) +{ + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->cancel(); + } + updateMaxComplexity(); +} + +void LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable() +{ + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->refresh(); + } + + refreshEnabledGraphics(); +} + +void LLFloaterPreferenceGraphicsAdvanced::onAdvancedAtmosphericsEnable() +{ + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->refresh(); + } + + refreshEnabledGraphics(); +} + +void LLFloaterPreferenceGraphicsAdvanced::refresh() +{ + getChild<LLUICtrl>("fsaa")->setValue((LLSD::Integer) gSavedSettings.getU32("RenderFSAASamples")); + + // sliders and their text boxes + // mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow"); + // slider text boxes + updateSliderText(getChild<LLSliderCtrl>("ObjectMeshDetail", true), getChild<LLTextBox>("ObjectMeshDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail", true), getChild<LLTextBox>("FlexibleMeshDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail", true), getChild<LLTextBox>("TreeMeshDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail", true), getChild<LLTextBox>("AvatarMeshDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail", true), getChild<LLTextBox>("AvatarPhysicsDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true)); + updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true)); + updateSliderText(getChild<LLSliderCtrl>("TerrainDetail", true), getChild<LLTextBox>("TerrainDetailText", true)); + LLAvatarComplexityControls::setIndirectControls(); + setMaxNonImpostorsText( + gSavedSettings.getU32("RenderAvatarMaxNonImpostors"), + getChild<LLTextBox>("IndirectMaxNonImpostorsText", true)); + LLAvatarComplexityControls::setText( + gSavedSettings.getU32("RenderAvatarMaxComplexity"), + getChild<LLTextBox>("IndirectMaxComplexityText", true)); + refreshEnabledState(); +} + +void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledGraphics() +{ + refreshEnabledState(); +} + +void LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity() +{ + // Called when the IndirectMaxComplexity control changes + LLAvatarComplexityControls::updateMax( + getChild<LLSliderCtrl>("IndirectMaxComplexity"), + getChild<LLTextBox>("IndirectMaxComplexityText")); +} + +void LLFloaterPreferenceGraphicsAdvanced::updateComplexityText() +{ + LLAvatarComplexityControls::setText(gSavedSettings.getU32("RenderAvatarMaxComplexity"), + getChild<LLTextBox>("IndirectMaxComplexityText", true)); +} + +void LLFloaterPreferenceGraphicsAdvanced::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box) +{ + if (text_box == NULL || ctrl== NULL) + return; + + // get range and points when text should change + F32 value = (F32)ctrl->getValue().asReal(); + F32 min = ctrl->getMinValue(); + F32 max = ctrl->getMaxValue(); + F32 range = max - min; + llassert(range > 0); + F32 midPoint = min + range / 3.0f; + F32 highPoint = min + (2.0f * range / 3.0f); + + // choose the right text + if (value < midPoint) + { + text_box->setText(LLTrans::getString("GraphicsQualityLow")); + } + else if (value < highPoint) + { + text_box->setText(LLTrans::getString("GraphicsQualityMid")); + } + else + { + text_box->setText(LLTrans::getString("GraphicsQualityHigh")); + } +} + +void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors() +{ + // Called when the IndirectMaxNonImpostors control changes + // Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors + LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors",true); + U32 value = ctrl->getValue().asInteger(); + + if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value) + { + value=0; + } + gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value); + LLVOAvatar::updateImpostorRendering(value); // make it effective immediately + setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); +} + +void LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors(const LLSD& newvalue) +{ + U32 value = newvalue.asInteger(); + if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors"))) + { + gSavedSettings.setU32("IndirectMaxNonImpostors", value); + setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); + } +} + +void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box) +{ + if (0 == value) + { + text_box->setText(LLTrans::getString("no_limit")); + } + else + { + text_box->setText(llformat("%d", value)); + } +} + +void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings() +{ + LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); + LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); + LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram"); + LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth"); + LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); + LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); + LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail"); + LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText"); + LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); + LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); + LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail"); + LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText"); + + // disabled windlight + if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) + { + ctrl_wind_light->setEnabled(FALSE); + ctrl_wind_light->setValue(FALSE); + + sky->setEnabled(FALSE); + sky_text->setEnabled(FALSE); + + //deferred needs windlight, disable deferred + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + shadows_text->setEnabled(FALSE); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_dof->setEnabled(FALSE); + ctrl_dof->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); + } + + // disabled deferred + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred")) + { + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + shadows_text->setEnabled(FALSE); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_dof->setEnabled(FALSE); + ctrl_dof->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); + } + + // disabled deferred SSAO + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) + { + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + } + + // disabled deferred shadows + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) + { + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + shadows_text->setEnabled(FALSE); + } + + // disabled reflections + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) + { + ctrl_reflections->setEnabled(FALSE); + ctrl_reflections->setValue(FALSE); + reflections_text->setEnabled(FALSE); + } + + // disabled av + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) + { + ctrl_avatar_vp->setEnabled(FALSE); + ctrl_avatar_vp->setValue(FALSE); + + ctrl_avatar_cloth->setEnabled(FALSE); + ctrl_avatar_cloth->setValue(FALSE); + + //deferred needs AvatarVP, disable deferred + ctrl_shadows->setEnabled(FALSE); + ctrl_shadows->setValue(0); + shadows_text->setEnabled(FALSE); + + ctrl_ssao->setEnabled(FALSE); + ctrl_ssao->setValue(FALSE); + + ctrl_dof->setEnabled(FALSE); + ctrl_dof->setValue(FALSE); + + ctrl_deferred->setEnabled(FALSE); + ctrl_deferred->setValue(FALSE); + } + + // disabled cloth + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) + { + ctrl_avatar_cloth->setEnabled(FALSE); + ctrl_avatar_cloth->setValue(FALSE); + } +} + +void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() +{ + LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); + LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); + + // Reflections + BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps; + ctrl_reflections->setEnabled(reflections); + reflections_text->setEnabled(reflections); + + // Bump & Shiny + LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny"); + bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); + bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE); + + // Avatar Mode + // Enable Avatar Shaders + LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram"); + // Avatar Render Mode + LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth"); + + bool avatar_vp_enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"); + if (LLViewerShaderMgr::sInitialized) + { + S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel; + avatar_vp_enabled = (max_avatar_shader > 0) ? TRUE : FALSE; + } + + ctrl_avatar_vp->setEnabled(avatar_vp_enabled); + + if (gSavedSettings.getBOOL("RenderAvatarVP") == FALSE) + { + ctrl_avatar_cloth->setEnabled(FALSE); + } + else + { + ctrl_avatar_cloth->setEnabled(TRUE); + } + + // Vertex Shaders, Global Shader Enable + // SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code + LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail"); // can be linked with control var + LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText"); + + terrain_detail->setEnabled(FALSE); + terrain_text->setEnabled(FALSE); + + // WindLight + LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); + LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail"); + LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText"); + ctrl_wind_light->setEnabled(TRUE); + sky->setEnabled(TRUE); + sky_text->setEnabled(TRUE); + + //Deferred/SSAO/Shadows + LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); + + BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && + ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && + (ctrl_wind_light->get()) ? TRUE : FALSE; + + ctrl_deferred->setEnabled(enabled); + + LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO"); + LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); + LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail"); + LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText"); + + // note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it + enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE); + + ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred")); + + ctrl_ssao->setEnabled(enabled); + ctrl_dof->setEnabled(enabled); + + enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"); + + ctrl_shadow->setEnabled(enabled); + shadow_text->setEnabled(enabled); + + // Hardware settings + F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); + S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); + S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); + getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value()); + getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); + + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || + !gGLManager.mHasVertexBufferObject) + { + getChildView("vbo")->setEnabled(FALSE); + } + + if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") || + !gGLManager.mHasVertexBufferObject) + { + getChildView("texture compression")->setEnabled(FALSE); + } + + // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance + LLUICtrl* gamma_ctrl = getChild<LLUICtrl>("gamma"); + gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders()); + getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders()); + getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders()); + getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred")); + + // now turn off any features that are unavailable + disableUnavailableSettings(); +} + +void LLFloaterPreferenceGraphicsAdvanced::onBtnOK(const LLSD& userdata) +{ + LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->onBtnOK(userdata); + } +} + +void LLFloaterPreferenceGraphicsAdvanced::onBtnCancel(const LLSD& userdata) +{ + LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->onBtnCancel(userdata); + } +} diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.h b/indra/newview/llfloaterpreferencesgraphicsadvanced.h new file mode 100644 index 0000000000..7f26ff8b00 --- /dev/null +++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.h @@ -0,0 +1,66 @@ +/** + * @file llfloaterpreferencesgraphicsadvanced.h + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERPREFERENCEGRAPHICSADVANCED_H +#define LLFLOATERPREFERENCEGRAPHICSADVANCED_H + +#include "llcontrol.h" +#include "llfloater.h" + +class LLSliderCtrl; +class LLTextBox; + +class LLFloaterPreferenceGraphicsAdvanced : public LLFloater +{ +public: + LLFloaterPreferenceGraphicsAdvanced(const LLSD& key); + ~LLFloaterPreferenceGraphicsAdvanced(); + /*virtual*/ BOOL postBuild(); + void onOpen(const LLSD& key); + void onClickCloseBtn(bool app_quitting); + void disableUnavailableSettings(); + void refreshEnabledGraphics(); + void refreshEnabledState(); + void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box); + void updateMaxNonImpostors(); + void updateIndirectMaxNonImpostors(const LLSD& newvalue); + void setMaxNonImpostorsText(U32 value, LLTextBox* text_box); + void updateMaxComplexity(); + void updateComplexityText(); + void refresh(); + // callback for when client modifies a render option + void onRenderOptionEnable(); + void onAdvancedAtmosphericsEnable(); + LOG_CLASS(LLFloaterPreferenceGraphicsAdvanced); + +protected: + void onBtnOK(const LLSD& userdata); + void onBtnCancel(const LLSD& userdata); + + boost::signals2::connection mComplexityChangedSignal; +}; + +#endif //LLFLOATERPREFERENCEGRAPHICSADVANCED_H + diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 175f1849cf..0c8e248538 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -984,6 +984,7 @@ private: //----------------------------------------------------------------------------- // gpu_benchmark() +// returns measured memory bandwidth of GPU in gigabytes per second //----------------------------------------------------------------------------- F32 gpu_benchmark() { diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 8058faa5c7..d7d6fa1893 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -67,7 +67,9 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) mNameColumn(p.name_column.column_name), mAllowCallingCardDrop(p.allow_calling_card_drop), mShortNames(p.short_names), - mPendingLookupsRemaining(0) + mPendingLookupsRemaining(0), + mHoverIconName("Info_Small"), + mNameListType(INDIVIDUAL) {} // public @@ -134,7 +136,12 @@ BOOL LLNameListCtrl::handleDragAndDrop( void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience) { - if(is_experience) + if (isSpecialType()) + { + mIconClickedSignal(avatar_id); + return; + } + if(is_experience) { LLFloaterReg::showInstance("experience_profile", avatar_id, true); return; @@ -215,14 +222,16 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) S32 column_index = getColumnIndexFromOffset(x); LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y)); LLFloater* floater = gFloaterView->getParentFloater(this); - if (floater + + + if (floater && floater->isFrontmost() && hit_item - && column_index == mNameColumnIndex) + && ((column_index == mNameColumnIndex) || isSpecialType())) { - // ...this is the column with the avatar name - LLUUID avatar_id = hit_item->getUUID(); - if (avatar_id.notNull()) + // ...this is the column with the avatar name + LLUUID item_id = isSpecialType() ? hit_item->getSpecialID() : hit_item->getUUID(); + if (item_id.notNull()) { // ...valid avatar id @@ -230,13 +239,13 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) if (hit_cell) { S32 row_index = getItemIndex(hit_item); - LLRect cell_rect = getCellRect(row_index, column_index); + LLRect cell_rect = getCellRect(row_index, isSpecialType() ? getNumColumns() - 1 : column_index); // Convert rect local to screen coordinates LLRect sticky_rect; localRectToScreen(cell_rect, &sticky_rect); // Spawn at right side of cell - LLPointer<LLUIImage> icon = LLUI::getUIImage("Info_Small"); + LLPointer<LLUIImage> icon = LLUI::getUIImage(mHoverIconName); S32 screenX = sticky_rect.mRight - info_icon_size; S32 screenY = sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight()) / 2; LLCoordGL pos(screenX, screenY); @@ -250,7 +259,7 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) LLToolTip::Params params; params.background_visible(false); - params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience)); + params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, item_id, is_group, is_experience)); params.delay_time(0.0f); // spawn instantly on hover params.image(icon); params.message(""); @@ -340,6 +349,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( // use supplied name by default std::string fullname = name_item.name; + switch(name_item.target) { case GROUP: @@ -358,8 +368,10 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( } break; case SPECIAL: - // just use supplied name - break; + { + item->setSpecialID(name_item.special_id()); + return item; + } case INDIVIDUAL: { LLAvatarName av_name; @@ -370,7 +382,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( else if (LLAvatarNameCache::get(id, &av_name)) { if (mShortNames) - fullname = av_name.getDisplayName(); + fullname = av_name.getDisplayName(true); else fullname = av_name.getCompleteName(); } @@ -440,7 +452,8 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id) for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) { LLScrollListItem* item = *it; - if (item->getUUID() == agent_id) + LLUUID cur_id = isSpecialType() ? dynamic_cast<LLNameListItem*>(item)->getSpecialID() : item->getUUID(); + if (cur_id == agent_id) { idx = getItemIndex(item); break; @@ -471,6 +484,34 @@ LLScrollListItem* LLNameListCtrl::getNameItemByAgentId(const LLUUID& agent_id) return NULL; } +void LLNameListCtrl::selectItemBySpecialId(const LLUUID& special_id) +{ + if (special_id.isNull()) + { + return; + } + + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) + { + LLNameListItem* item = dynamic_cast<LLNameListItem*>(*it); + if (item && item->getSpecialID() == special_id) + { + item->setSelected(TRUE); + break; + } + } +} + +LLUUID LLNameListCtrl::getSelectedSpecialId() +{ + LLNameListItem* item = dynamic_cast<LLNameListItem*>(getFirstSelected()); + if(item) + { + return item->getSpecialID(); + } + return LLUUID(); +} + void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 5dd5da5892..4a4bd4ba09 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -46,6 +46,8 @@ public: void setIsGroup(bool is_group) { mIsGroup = is_group; } bool isExperience() const { return mIsExperience; } void setIsExperience(bool is_experience) { mIsExperience = is_experience; } + void setSpecialID(const LLUUID& special_id) { mSpecialID = special_id; } + const LLUUID& getSpecialID() const { return mSpecialID; } protected: friend class LLNameListCtrl; @@ -68,6 +70,8 @@ protected: private: bool mIsGroup; bool mIsExperience; + + LLUUID mSpecialID; }; @@ -95,10 +99,12 @@ public: { Optional<std::string> name; Optional<ENameType, NameTypeNames> target; + Optional<LLUUID> special_id; NameItem() : name("name"), - target("target", INDIVIDUAL) + target("target", INDIVIDUAL), + special_id("special_id", LLUUID()) {} }; @@ -156,6 +162,9 @@ public: LLScrollListItem* getNameItemByAgentId(const LLUUID& agent_id); + void selectItemBySpecialId(const LLUUID& special_id); + LLUUID getSelectedSpecialId(); + // LLView interface /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, @@ -170,7 +179,14 @@ public: /*virtual*/ void updateColumns(bool force_update); /*virtual*/ void mouseOverHighlightNthItem( S32 index ); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + + bool isSpecialType() { return (mNameListType == SPECIAL); } + + void setNameListType(e_name_type type) { mNameListType = type; } + void setHoverIconName(std::string icon_name) { mHoverIconName = icon_name; } + private: void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false); void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, std::string prefix, LLHandle<LLNameListItem> item); @@ -187,6 +203,11 @@ private: S32 mPendingLookupsRemaining; namelist_complete_signal_t mNameListCompleteSignal; + + std::string mHoverIconName; + e_name_type mNameListType; + + boost::signals2::signal<void(const LLUUID &)> mIconClickedSignal; public: boost::signals2::connection setOnNameListCompleteCallback(boost::function<void(bool)> onNameListCompleteCallback) @@ -194,6 +215,10 @@ public: return mNameListCompleteSignal.connect(onNameListCompleteCallback); } + boost::signals2::connection setIconClickedCallback(boost::function<void(const LLUUID &)> cb) + { + return mIconClickedSignal.connect(cb); + } }; diff --git a/indra/newview/llperfstats.cpp b/indra/newview/llperfstats.cpp new file mode 100644 index 0000000000..1a0e5842e2 --- /dev/null +++ b/indra/newview/llperfstats.cpp @@ -0,0 +1,469 @@ +/** +* @file llperfstats.cpp +* @brief Statistics collection to support autotune and perf flaoter. +* +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2022, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llperfstats.h" +#include "llcontrol.h" +#include "pipeline.h" +#include "llagentcamera.h" +#include "llvoavatar.h" +#include "llworld.h" +#include <llthread.h> + +extern LLControlGroup gSavedSettings; + +namespace LLPerfStats +{ + std::atomic<int64_t> tunedAvatars{0}; + std::atomic<U64> renderAvatarMaxART_ns{(U64)(ART_UNLIMITED_NANOS)}; // highest render time we'll allow without culling features + bool belowTargetFPS{false}; + U32 lastGlobalPrefChange{0}; + std::mutex bufferToggleLock{}; + + Tunables tunables; + + std::atomic<int> StatsRecorder::writeBuffer{0}; + bool StatsRecorder::collectionEnabled{true}; + LLUUID StatsRecorder::focusAv{LLUUID::null}; + std::array<StatsRecorder::StatsTypeMatrix,2> StatsRecorder::statsDoubleBuffer{ {} }; + std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::max{ {} }; + std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::sum{ {} }; + + void Tunables::applyUpdates() + { + assert_main_thread(); + // these following variables are proxies for pipeline statics we do not need a two way update (no llviewercontrol handler) + if( tuningFlag & NonImpostors ){ gSavedSettings.setU32("IndirectMaxNonImpostors", nonImpostors); }; + if( tuningFlag & ReflectionDetail ){ gSavedSettings.setS32("RenderReflectionDetail", reflectionDetail); }; + if( tuningFlag & FarClip ){ gSavedSettings.setF32("RenderFarClip", farClip); }; + if( tuningFlag & UserMinDrawDistance ){ gSavedSettings.setF32("AutoTuneRenderFarClipMin", userMinDrawDistance); }; + if( tuningFlag & UserTargetDrawDistance ){ gSavedSettings.setF32("AutoTuneRenderFarClipTarget", userTargetDrawDistance); }; + if( tuningFlag & UserImpostorDistance ){ gSavedSettings.setF32("AutoTuneImpostorFarAwayDistance", userImpostorDistance); }; + if( tuningFlag & UserImpostorDistanceTuningEnabled ){ gSavedSettings.setBOOL("AutoTuneImpostorByDistEnabled", userImpostorDistanceTuningEnabled); }; + if( tuningFlag & UserFPSTuningStrategy ){ gSavedSettings.setU32("TuningFPSStrategy", userFPSTuningStrategy); }; + if( tuningFlag & UserAutoTuneEnabled ){ gSavedSettings.setBOOL("AutoTuneFPS", userAutoTuneEnabled); }; + if( tuningFlag & UserAutoTuneLock ){ gSavedSettings.setBOOL("AutoTuneLock", userAutoTuneLock); }; + if( tuningFlag & UserTargetFPS ){ gSavedSettings.setU32("TargetFPS", userTargetFPS); }; + if( tuningFlag & UserTargetReflections ){ gSavedSettings.setS32("UserTargetReflections", userTargetReflections); }; + // Note: The Max ART slider is logarithmic and thus we have an intermediate proxy value + if( tuningFlag & UserARTCutoff ){ gSavedSettings.setF32("RenderAvatarMaxART", userARTCutoffSliderValue); }; + resetChanges(); + } + + void Tunables::updateRenderCostLimitFromSettings() + { + assert_main_thread(); + const auto newval = gSavedSettings.getF32("RenderAvatarMaxART"); + if(newval < log10(LLPerfStats::ART_UNLIMITED_NANOS/1000)) + { + LLPerfStats::renderAvatarMaxART_ns = pow(10,newval)*1000; + } + else + { + LLPerfStats::renderAvatarMaxART_ns = 0; + } + } + + // static + void Tunables::updateSettingsFromRenderCostLimit() + { + if( userARTCutoffSliderValue != log10( ( (F32)LLPerfStats::renderAvatarMaxART_ns )/1000 ) ) + { + if( LLPerfStats::renderAvatarMaxART_ns != 0 ) + { + updateUserARTCutoffSlider(log10( ( (F32)LLPerfStats::renderAvatarMaxART_ns )/1000 ) ); + } + else + { + updateUserARTCutoffSlider(log10( (F32)LLPerfStats::ART_UNLIMITED_NANOS/1000 ) ); + } + } + } + + void Tunables::initialiseFromSettings() + { + assert_main_thread(); + // the following variables are two way and have "push" in llviewercontrol + LLPerfStats::tunables.userMinDrawDistance = gSavedSettings.getF32("AutoTuneRenderFarClipMin"); + LLPerfStats::tunables.userTargetDrawDistance = gSavedSettings.getF32("AutoTuneRenderFarClipTarget"); + LLPerfStats::tunables.userImpostorDistance = gSavedSettings.getF32("AutoTuneImpostorFarAwayDistance"); + LLPerfStats::tunables.userImpostorDistanceTuningEnabled = gSavedSettings.getBOOL("AutoTuneImpostorByDistEnabled"); + LLPerfStats::tunables.userFPSTuningStrategy = gSavedSettings.getU32("TuningFPSStrategy"); + LLPerfStats::tunables.userTargetFPS = gSavedSettings.getU32("TargetFPS"); + LLPerfStats::tunables.userTargetReflections = gSavedSettings.getS32("UserTargetReflections"); + LLPerfStats::tunables.userAutoTuneEnabled = gSavedSettings.getBOOL("AutoTuneFPS"); + LLPerfStats::tunables.userAutoTuneLock = gSavedSettings.getBOOL("AutoTuneLock"); + // Note: The Max ART slider is logarithmic and thus we have an intermediate proxy value + updateRenderCostLimitFromSettings(); + resetChanges(); + } + + StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run) + { + // create a queue + // create a thread to consume from the queue + tunables.initialiseFromSettings(); + t.detach(); + } + + // static + void StatsRecorder::toggleBuffer() + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + using ST = StatType_t; + + bool unreliable{false}; + LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FRAME); + auto& sceneStats = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null]; + auto& lastStats = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null]; + + static constexpr std::initializer_list<StatType_t> sceneStatsToAvg = { + StatType_t::RENDER_FRAME, + StatType_t::RENDER_DISPLAY, + StatType_t::RENDER_HUDS, + StatType_t::RENDER_UI, + StatType_t::RENDER_SWAP, + // RENDER_LFS, + // RENDER_MESHREPO, + StatType_t::RENDER_IDLE }; + + static constexpr std::initializer_list<StatType_t> avatarStatsToAvg = { + StatType_t::RENDER_GEOMETRY, + StatType_t::RENDER_SHADOWS, + StatType_t::RENDER_COMBINED, + StatType_t::RENDER_IDLE }; + + + if( /*sceneStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)] != 0 ||*/ sceneStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)] != 0 ) + { + unreliable = true; + //lastStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)]; + lastStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)]; + lastStats[static_cast<size_t>(StatType_t::RENDER_FRAME)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_FRAME)]; // bring over the total frame render time to deal with region crossing overlap issues + } + + if(!unreliable) + { + // only use these stats when things are reliable. + + for(auto & statEntry : sceneStatsToAvg) + { + auto avg = lastStats[static_cast<size_t>(statEntry)]; + auto val = sceneStats[static_cast<size_t>(statEntry)]; + sceneStats[static_cast<size_t>(statEntry)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS); + // LL_INFOS("scenestats") << "Scenestat: " << static_cast<size_t>(statEntry) << " before=" << avg << " new=" << val << " newavg=" << statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(statEntry)] << LL_ENDL; + } + } +// Allow attachment times etc to update even when FPS limited or sleeping. + auto& statsMap = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)]; + for(auto& stat_entry : statsMap) + { + auto val = stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)]; + if(val > SMOOTHING_PERIODS){ + auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)][stat_entry.first][static_cast<size_t>(ST::RENDER_COMBINED)]; + stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS); + } + } + + + auto& statsMapAv = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_AVATAR)]; + for(auto& stat_entry : statsMapAv) + { + for(auto& stat : avatarStatsToAvg) + { + auto val = stat_entry.second[static_cast<size_t>(stat)]; + if(val > SMOOTHING_PERIODS) + { + auto avg = statsDoubleBuffer[writeBuffer ^ 1][static_cast<size_t>(ObjType_t::OT_AVATAR)][stat_entry.first][static_cast<size_t>(stat)]; + stat_entry.second[static_cast<size_t>(stat)] = avg + (val / SMOOTHING_PERIODS) - (avg / SMOOTHING_PERIODS); + } + } + } + + // swap the buffers + if(enabled()) + { + std::lock_guard<std::mutex> lock{bufferToggleLock}; + writeBuffer ^= 1; + }; // note we are relying on atomic updates here. The risk is low and would cause minor errors in the stats display. + + // clean the write maps in all cases. + auto& statsTypeMatrix = statsDoubleBuffer[writeBuffer]; + for(auto& statsMapByType : statsTypeMatrix) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_STATS("Clear stats maps"); + for(auto& stat_entry : statsMapByType) + { + std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0); + } + statsMapByType.clear(); + } + for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_STATS("clear max/sum"); + max[writeBuffer][i].fill(0); + sum[writeBuffer][i].fill(0); + } + + // and now adjust the proxy vars so that the main thread can adjust the visuals. + if(tunables.userAutoTuneEnabled) + { + updateAvatarParams(); + } + } + + // clear buffers when we change region or need a hard reset. + // static + void StatsRecorder::clearStatsBuffers() + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + using ST = StatType_t; + + auto& statsTypeMatrix = statsDoubleBuffer[writeBuffer]; + for(auto& statsMap : statsTypeMatrix) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_STATS("Clear stats maps"); + for(auto& stat_entry : statsMap) + { + std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0); + } + statsMap.clear(); + } + for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_STATS("clear max/sum"); + max[writeBuffer][i].fill(0); + sum[writeBuffer][i].fill(0); + } + // swap the clean buffers in + if(enabled()) + { + std::lock_guard<std::mutex> lock{bufferToggleLock}; + writeBuffer ^= 1; + }; + // repeat before we start processing new stuff + for(auto& statsMap : statsTypeMatrix) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_STATS("Clear stats maps"); + for(auto& stat_entry : statsMap) + { + std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0); + } + statsMap.clear(); + } + for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_STATS("clear max/sum"); + max[writeBuffer][i].fill(0); + sum[writeBuffer][i].fill(0); + } + } + + //static + int StatsRecorder::countNearbyAvatars(S32 distance) + { + const auto our_pos = gAgentCamera.getCameraPositionGlobal(); + + std::vector<LLVector3d> positions; + uuid_vec_t avatar_ids; + LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, our_pos, distance); + return positions.size(); + } + + // static + void StatsRecorder::updateAvatarParams() + { + + if(tunables.userImpostorDistanceTuningEnabled) + { + // if we have less than the user's "max Non-Impostors" avatars within the desired range then adjust the limit. + // also adjusts back up again for nearby crowds. + auto count = countNearbyAvatars(std::min(LLPipeline::RenderFarClip, tunables.userImpostorDistance)); + if( count != tunables.nonImpostors ) + { + tunables.updateNonImposters( (count < LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER)?count : LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER ); + LL_DEBUGS("AutoTune") << "There are " << count << "avatars within " << std::min(LLPipeline::RenderFarClip, tunables.userImpostorDistance) << "m of the camera" << LL_ENDL; + } + } + + auto av_render_max_raw = LLPerfStats::StatsRecorder::getMax(ObjType_t::OT_AVATAR, LLPerfStats::StatType_t::RENDER_COMBINED); + // Is our target frame time lower than current? If so we need to take action to reduce draw overheads. + // cumulative avatar time (includes idle processing, attachments and base av) + auto tot_avatar_time_raw = LLPerfStats::StatsRecorder::getSum(ObjType_t::OT_AVATAR, LLPerfStats::StatType_t::RENDER_COMBINED); + // sleep time is basically forced sleep when window out of focus + auto tot_sleep_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_SLEEP); + // similar to sleep time, induced by FPS limit + //auto tot_limit_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FPSLIMIT); + + + // the time spent this frame on the "doFrame" call. Treated as "tot time for frame" + auto tot_frame_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FRAME); + + if( tot_sleep_time_raw != 0 ) + { + // Note: we do not average sleep + // if at some point we need to, the averaging will need to take this into account or + // we forever think we're in the background due to residuals. + LL_DEBUGS() << "No tuning when not in focus" << LL_ENDL; + return; + } + + // The frametime budget we have based on the target FPS selected + auto target_frame_time_raw = (U64)llround((F64)LLTrace::BlockTimer::countsPerSecond()/(tunables.userTargetFPS==0?1:tunables.userTargetFPS)); + // LL_INFOS() << "Effective FPS(raw):" << tot_frame_time_raw << " Target:" << target_frame_time_raw << LL_ENDL; + auto inferredFPS{1000/(U32)std::max(raw_to_ms(tot_frame_time_raw),1.0)}; + U32 settingsChangeFrequency{inferredFPS > 25?inferredFPS:25}; + /*if( tot_limit_time_raw != 0) + { + // This could be problematic. + tot_frame_time_raw -= tot_limit_time_raw; + }*/ + // 1) Is the target frame time lower than current? + if( target_frame_time_raw <= tot_frame_time_raw ) + { + if(belowTargetFPS == false) + { + // this is the first frame under. hold fire to add a little hysteresis + belowTargetFPS = true; + LLPerfStats::lastGlobalPrefChange = gFrameCount; + } + // if so we've got work to do + + // how much of the frame was spent on non avatar related work? + U64 non_avatar_time_raw = tot_frame_time_raw - tot_avatar_time_raw; + + // If the target frame time < scene time (estimated as non_avatar time) + U64 target_avatar_time_raw; + if(target_frame_time_raw < non_avatar_time_raw) + { + // we cannnot do this by avatar adjustment alone. + if((gFrameCount - LLPerfStats::lastGlobalPrefChange) > settingsChangeFrequency) // give changes a short time to take effect. + { + if(tunables.userFPSTuningStrategy == TUNE_SCENE_AND_AVATARS) + { + // 1 - hack the water to opaque. all non opaque have a significant hit, this is a big boost for (arguably) a minor visual hit. + // the other reflection options make comparatively little change and if this overshoots we'll be stepping back up later + if(LLPipeline::RenderReflectionDetail != -2) + { + LLPerfStats::tunables.updateReflectionDetail(-2); + LLPerfStats::lastGlobalPrefChange = gFrameCount; + return; + } + else // deliberately "else" here so we only do one of these in any given frame + { + // step down the DD by 10m per update + auto new_dd = (LLPipeline::RenderFarClip - DD_STEP > tunables.userMinDrawDistance)?(LLPipeline::RenderFarClip - DD_STEP) : tunables.userMinDrawDistance; + if(new_dd != LLPipeline::RenderFarClip) + { + LLPerfStats::tunables.updateFarClip( new_dd ); + LLPerfStats::lastGlobalPrefChange = gFrameCount; + return; + } + } + } + // if we reach here, we've no more changes to make to tune scenery so we'll resort to agressive Avatar tuning + // Note: moved from outside "if changefrequency elapsed" to stop fallthrough and allow scenery changes time to take effect. + target_avatar_time_raw = 0; + } + else + { + // we made a settings change recently so let's give it time. + return; + } + } + else + { + // set desired avatar budget. + target_avatar_time_raw = target_frame_time_raw - non_avatar_time_raw; + } + + if( target_avatar_time_raw < tot_avatar_time_raw ) + { + // we need to spend less time drawing avatars to meet our budget + auto new_render_limit_ns {LLPerfStats::raw_to_ns(av_render_max_raw)}; + // max render this frame may be higher than the last (cos new entrants and jitter) so make sure we are heading in the right direction + if( new_render_limit_ns > renderAvatarMaxART_ns ) + { + new_render_limit_ns = renderAvatarMaxART_ns; + } + new_render_limit_ns -= LLPerfStats::ART_MIN_ADJUST_DOWN_NANOS; + + // bounce at the bottom to prevent "no limit" + new_render_limit_ns = std::max((U64)new_render_limit_ns, (U64)LLPerfStats::ART_MINIMUM_NANOS); + + // assign the new value + if(renderAvatarMaxART_ns != new_render_limit_ns) + { + renderAvatarMaxART_ns = new_render_limit_ns; + tunables.updateSettingsFromRenderCostLimit(); + } + // LL_DEBUGS() << "AUTO_TUNE: avatar_budget adjusted to:" << new_render_limit_ns << LL_ENDL; + } + // LL_DEBUGS() << "AUTO_TUNE: Target frame time:"<< LLPerfStats::raw_to_us(target_frame_time_raw) << "usecs (non_avatar is " << LLPerfStats::raw_to_us(non_avatar_time_raw) << "usecs) Max cost limited=" << renderAvatarMaxART_ns << LL_ENDL; + } + else if( LLPerfStats::raw_to_ns(target_frame_time_raw) > (LLPerfStats::raw_to_ns(tot_frame_time_raw) + renderAvatarMaxART_ns) ) + { + if(belowTargetFPS == true) + { + // we reached target, force a pause + lastGlobalPrefChange = gFrameCount; + belowTargetFPS = false; + } + + // once we're over the FPS target we slow down further + if((gFrameCount - lastGlobalPrefChange) > settingsChangeFrequency*3) + { + if(!tunables.userAutoTuneLock) + { + // we've reached the target and stayed long enough to consider stable. + // turn off if we are not locked. + tunables.updateUserAutoTuneEnabled(false); + } + if( LLPerfStats::tunedAvatars > 0 ) + { + // if we have more time to spare let's shift up little in the hope we'll restore an avatar. + renderAvatarMaxART_ns += LLPerfStats::ART_MIN_ADJUST_UP_NANOS; + tunables.updateSettingsFromRenderCostLimit(); + return; + } + if(tunables.userFPSTuningStrategy == TUNE_SCENE_AND_AVATARS) + { + if( LLPipeline::RenderFarClip < tunables.userTargetDrawDistance ) + { + LLPerfStats::tunables.updateFarClip( std::min(LLPipeline::RenderFarClip + DD_STEP, tunables.userTargetDrawDistance) ); + LLPerfStats::lastGlobalPrefChange = gFrameCount; + return; + } + if( (tot_frame_time_raw * 1.5) < target_frame_time_raw ) + { + // if everything else is "max" and we have >50% headroom let's knock the water quality up a notch at a time. + LLPerfStats::tunables.updateReflectionDetail( std::min(LLPipeline::RenderReflectionDetail + 1, tunables.userTargetReflections) ); + } + } + } + } + } +} diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h new file mode 100644 index 0000000000..961594f18c --- /dev/null +++ b/indra/newview/llperfstats.h @@ -0,0 +1,454 @@ +/** +* @file llperfstats.h +* @brief Statistics collection to support autotune and perf flaoter. +* +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2022, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#pragma once +#ifndef LL_PERFSTATS_H_INCLUDED +#define LL_PERFSTATS_H_INCLUDED + +#include <atomic> +#include <chrono> +#include <array> +#include <unordered_map> +#include <mutex> +#include "lluuid.h" +#include "llfasttimer.h" +#include "llapp.h" +#include "llprofiler.h" +#include "pipeline.h" + +extern U32 gFrameCount; +extern LLUUID gAgentID; +namespace LLPerfStats +{ +// Note if changing these, they should correspond with the log range of the correpsonding sliders + static constexpr U64 ART_UNLIMITED_NANOS{50000000}; + static constexpr U64 ART_MINIMUM_NANOS{100000}; + static constexpr U64 ART_MIN_ADJUST_UP_NANOS{10000}; + static constexpr U64 ART_MIN_ADJUST_DOWN_NANOS{10000}; + + static constexpr F32 PREFERRED_DD{180}; + static constexpr U32 SMOOTHING_PERIODS{50}; + static constexpr U32 DD_STEP{10}; + + static constexpr U32 TUNE_AVATARS_ONLY{0}; + static constexpr U32 TUNE_SCENE_AND_AVATARS{1}; + + extern std::atomic<int64_t> tunedAvatars; + extern std::atomic<U64> renderAvatarMaxART_ns; + extern bool belowTargetFPS; + extern U32 lastGlobalPrefChange; + extern std::mutex bufferToggleLock; + + enum class ObjType_t{ + OT_GENERAL=0, // Also Unknown. Used for n/a type stats such as scenery + OT_AVATAR, + OT_ATTACHMENT, + OT_HUD, + OT_COUNT + }; + enum class StatType_t{ + RENDER_GEOMETRY=0, + RENDER_SHADOWS, + RENDER_HUDS, + RENDER_UI, + RENDER_COMBINED, + RENDER_SWAP, + RENDER_FRAME, + RENDER_DISPLAY, + RENDER_SLEEP, + RENDER_LFS, + RENDER_MESHREPO, + //RENDER_FPSLIMIT, + RENDER_FPS, + RENDER_IDLE, + RENDER_DONE, // toggle buffer & clearbuffer (see processUpdate for hackery) + STATS_COUNT + }; + + struct StatsRecord + { + StatType_t statType; + ObjType_t objType; + LLUUID avID; + LLUUID objID; + uint64_t time; + bool isRigged; + bool isHUD; + }; + + struct Tunables + { + static constexpr U32 Nothing{0}; + static constexpr U32 NonImpostors{1}; + static constexpr U32 ReflectionDetail{2}; + static constexpr U32 FarClip{4}; + static constexpr U32 UserMinDrawDistance{8}; + static constexpr U32 UserTargetDrawDistance{16}; + static constexpr U32 UserImpostorDistance{32}; + static constexpr U32 UserImpostorDistanceTuningEnabled{64}; + static constexpr U32 UserFPSTuningStrategy{128}; + static constexpr U32 UserAutoTuneEnabled{256}; + static constexpr U32 UserTargetFPS{512}; + static constexpr U32 UserARTCutoff{1024}; + static constexpr U32 UserTargetReflections{2048}; + static constexpr U32 UserAutoTuneLock{4096}; + + U32 tuningFlag{0}; // bit mask for changed settings + + // proxy variables, used to pas the new value to be set via the mainthread + U32 nonImpostors{0}; + S32 reflectionDetail{0}; + F32 farClip{0.0}; + F32 userMinDrawDistance{0.0}; + F32 userTargetDrawDistance{0.0}; + F32 userImpostorDistance{0.0}; + bool userImpostorDistanceTuningEnabled{false}; + U32 userFPSTuningStrategy{0}; + bool userAutoTuneEnabled{false}; + bool userAutoTuneLock{true}; + U32 userTargetFPS{0}; + F32 userARTCutoffSliderValue{0}; + S32 userTargetReflections{0}; + + void updateNonImposters(U32 nv){nonImpostors=nv; tuningFlag |= NonImpostors;}; + void updateReflectionDetail(S32 nv){reflectionDetail=nv; tuningFlag |= ReflectionDetail;}; + void updateFarClip(F32 nv){farClip=nv; tuningFlag |= FarClip;}; + void updateUserMinDrawDistance(F32 nv){userMinDrawDistance=nv; tuningFlag |= UserMinDrawDistance;}; + void updateUserTargetDrawDistance(F32 nv){userTargetDrawDistance=nv; tuningFlag |= UserTargetDrawDistance;}; + void updateImposterDistance(F32 nv){userImpostorDistance=nv; tuningFlag |= UserImpostorDistance;}; + void updateImposterDistanceTuningEnabled(bool nv){userImpostorDistanceTuningEnabled=nv; tuningFlag |= UserImpostorDistanceTuningEnabled;}; + void updateUserFPSTuningStrategy(U32 nv){userFPSTuningStrategy=nv; tuningFlag |= UserFPSTuningStrategy;}; + void updateTargetFps(U32 nv){userTargetFPS=nv; tuningFlag |= UserTargetFPS;}; + void updateUserARTCutoffSlider(F32 nv){userARTCutoffSliderValue=nv; tuningFlag |= UserARTCutoff;}; + void updateUserAutoTuneEnabled(bool nv){userAutoTuneEnabled=nv; tuningFlag |= UserAutoTuneEnabled;}; + void updateUserAutoTuneLock(bool nv){userAutoTuneLock=nv; tuningFlag |= UserAutoTuneLock;}; + void updateUserTargetReflections(S32 nv){userTargetReflections=nv; tuningFlag |= UserTargetReflections;}; + + void resetChanges(){tuningFlag=Nothing;}; + void initialiseFromSettings(); + void updateRenderCostLimitFromSettings(); + void updateSettingsFromRenderCostLimit(); + void applyUpdates(); + }; + + extern Tunables tunables; + + class StatsRecorder{ + using Queue = LLThreadSafeQueue<StatsRecord>; + public: + + static inline StatsRecorder& getInstance() + { + static StatsRecorder instance; + return instance; + } + static inline void setFocusAv(const LLUUID& avID){focusAv = avID;}; + static inline const LLUUID& getFocusAv(){return focusAv;}; + static inline void send(StatsRecord && upd){StatsRecorder::getInstance().q.pushFront(std::move(upd));}; + static void endFrame(){StatsRecorder::getInstance().q.pushFront(StatsRecord{StatType_t::RENDER_DONE, ObjType_t::OT_GENERAL, LLUUID::null, LLUUID::null, 0});}; + static void clearStats(){StatsRecorder::getInstance().q.pushFront(StatsRecord{StatType_t::RENDER_DONE, ObjType_t::OT_GENERAL, LLUUID::null, LLUUID::null, 1});}; + + static inline void setEnabled(bool on_or_off){collectionEnabled=on_or_off;}; + static inline void enable() { collectionEnabled=true; }; + static inline void disable() { collectionEnabled=false; }; + static inline bool enabled() { return collectionEnabled; }; + + static inline int getReadBufferIndex() { return (writeBuffer ^ 1); }; + // static inline const StatsTypeMatrix& getCurrentStatsMatrix(){ return statsDoubleBuffer[getReadBufferIndex()];} + static inline uint64_t get(ObjType_t otype, LLUUID id, StatType_t type) + { + return statsDoubleBuffer[getReadBufferIndex()][static_cast<size_t>(otype)][id][static_cast<size_t>(type)]; + } + static inline uint64_t getSceneStat(StatType_t type) + { + return statsDoubleBuffer[getReadBufferIndex()][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(type)]; + } + + static inline uint64_t getSum(ObjType_t otype, StatType_t type) + { + return sum[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)]; + } + static inline uint64_t getMax(ObjType_t otype, StatType_t type) + { + return max[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)]; + } + static void updateAvatarParams(); + private: + StatsRecorder(); + + static int countNearbyAvatars(S32 distance); +// StatsArray is a uint64_t for each possible statistic type. + using StatsArray = std::array<uint64_t, static_cast<size_t>(LLPerfStats::StatType_t::STATS_COUNT)>; + using StatsMap = std::unordered_map<LLUUID, StatsArray, boost::hash<LLUUID>>; + using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>; + using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>; + + static std::atomic<int> writeBuffer; + static LLUUID focusAv; + static std::array<StatsTypeMatrix,2> statsDoubleBuffer; + static std::array<StatsSummaryArray,2> max; + static std::array<StatsSummaryArray,2> sum; + static bool collectionEnabled; + + + void processUpdate(const StatsRecord& upd) const + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + // LL_INFOS("perfstats") << "processing update:" << LL_ENDL; + // Note: nullptr is used as the key for global stats + #ifdef TRACY_ENABLE + static char avstr[36]; + static char obstr[36]; + #endif + + if (upd.statType == StatType_t::RENDER_DONE && upd.objType == ObjType_t::OT_GENERAL && upd.time == 0) + { + // LL_INFOS("perfstats") << "End of Frame Toggle Buffer:" << gFrameCount << LL_ENDL; + toggleBuffer(); + return; + } + if (upd.statType == StatType_t::RENDER_DONE && upd.objType == ObjType_t::OT_GENERAL && upd.time == 1) + { + // LL_INFOS("perfstats") << "New region - clear buffers:" << gFrameCount << LL_ENDL; + clearStatsBuffers(); + return; + } + + auto ot{upd.objType}; + auto& key{upd.objID}; + auto& avKey{upd.avID}; + auto type {upd.statType}; + auto val {upd.time}; + + if (ot == ObjType_t::OT_GENERAL) + { + // LL_INFOS("perfstats") << "General update:" << LL_ENDL; + doUpd(key, ot, type,val); + return; + } + + if (ot == ObjType_t::OT_AVATAR) + { + // LL_INFOS("perfstats") << "Avatar update:" << LL_ENDL; + doUpd(avKey, ot, type, val); + return; + } + + if (ot == ObjType_t::OT_ATTACHMENT) + { + if( !upd.isHUD ) // don't include HUD cost in self. + { + LL_PROFILE_ZONE_NAMED("Att as Av") + // For all attachments that are not rigged we add them to the avatar (for all avatars) cost. + doUpd(avKey, ObjType_t::OT_AVATAR, type, val); + } + if( avKey == focusAv ) + { + LL_PROFILE_ZONE_NAMED("Att as Att") + // For attachments that are for the focusAv (self for now) we record them for the attachment/complexity view + if(upd.isHUD) + { + ot = ObjType_t::OT_HUD; + } + // LL_INFOS("perfstats") << "frame: " << gFrameCount << " Attachment update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << LL_ENDL; + doUpd(key, ot, type, val); + } + // else + // { + // // LL_INFOS("perfstats") << "frame: " << gFrameCount << " non-self Att update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << " for av " << avKey.asString() << LL_ENDL; + // } + } + } + + static inline void doUpd(const LLUUID& key, ObjType_t ot, StatType_t type, uint64_t val) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + using ST = StatType_t; + StatsMap& stm {statsDoubleBuffer[writeBuffer][static_cast<size_t>(ot)]}; + auto& thisAsset = stm[key]; + + thisAsset[static_cast<size_t>(type)] += val; + thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)] += val; + + sum[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] += val; + sum[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] += val; + + if(max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] < thisAsset[static_cast<size_t>(type)]) + { + max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] = thisAsset[static_cast<size_t>(type)]; + } + if(max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] < thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)]) + { + max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] = thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)]; + } + } + + static void toggleBuffer(); + static void clearStatsBuffers(); + + // thread entry + static void run() + { + StatsRecord upd[10]; + auto & instance {StatsRecorder::getInstance()}; + LL_PROFILER_SET_THREAD_NAME("PerfStats"); + + while( enabled() && !LLApp::isExiting() ) + { + auto count = 0; + while (count < 10) + { + if (instance.q.tryPopFor(std::chrono::milliseconds(10), upd[count])) + { + count++; + } + else + { + break; + } + } + //LL_PROFILER_THREAD_BEGIN("PerfStats"); + if(count) + { + // LL_INFOS("perfstats") << "processing " << count << " updates." << LL_ENDL; + for(auto i =0; i < count; i++) + { + instance.processUpdate(upd[i]); + } + } + //LL_PROFILER_THREAD_END("PerfStats"); + } + } + + Queue q; + std::thread t; + + ~StatsRecorder() = default; + StatsRecorder(const StatsRecorder&) = delete; + StatsRecorder& operator=(const StatsRecorder&) = delete; + + }; + + template <enum ObjType_t ObjTypeDiscriminator> + class RecordTime + { + + private: + RecordTime(const RecordTime&) = delete; + RecordTime() = delete; + U64 start; + public: + StatsRecord stat; + + RecordTime( const LLUUID& av, const LLUUID& id, StatType_t type, bool isRiggedAtt=false, bool isHUDAtt=false): + start{LLTrace::BlockTimer::getCPUClockCount64()}, + stat{type, ObjTypeDiscriminator, std::move(av), std::move(id), 0, isRiggedAtt, isHUDAtt} + { + //LL_PROFILE_ZONE_COLOR(tracy::Color::Orange); + }; + + template < ObjType_t OD = ObjTypeDiscriminator, + std::enable_if_t<OD == ObjType_t::OT_GENERAL> * = nullptr> + explicit RecordTime( StatType_t type ):RecordTime<ObjTypeDiscriminator>(LLUUID::null, LLUUID::null, type ) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + }; + + template < ObjType_t OD = ObjTypeDiscriminator, + std::enable_if_t<OD == ObjType_t::OT_AVATAR> * = nullptr> + RecordTime( const LLUUID & av, StatType_t type ):RecordTime<ObjTypeDiscriminator>(std::move(av), LLUUID::null, type) + { + //LL_PROFILE_ZONE_COLOR(tracy::Color::Purple); + }; + + ~RecordTime() + { + if(!LLPerfStats::StatsRecorder::enabled()) + { + return; + } + + //LL_PROFILE_ZONE_COLOR(tracy::Color::Red); + + stat.time = LLTrace::BlockTimer::getCPUClockCount64() - start; + StatsRecorder::send(std::move(stat)); + }; + }; + + + inline double raw_to_ns(U64 raw) { return (static_cast<double>(raw) * 1000000000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); }; + inline double raw_to_us(U64 raw) { return (static_cast<double>(raw) * 1000000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); }; + inline double raw_to_ms(U64 raw) { return (static_cast<double>(raw) * 1000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); }; + + using RecordSceneTime = RecordTime<ObjType_t::OT_GENERAL>; + using RecordAvatarTime = RecordTime<ObjType_t::OT_AVATAR>; + using RecordAttachmentTime = RecordTime<ObjType_t::OT_ATTACHMENT>; + using RecordHudAttachmentTime = RecordTime<ObjType_t::OT_HUD>; + +};// namespace LLPerfStats + +// helper functions +using RATptr = std::unique_ptr<LLPerfStats::RecordAttachmentTime>; +using RSTptr = std::unique_ptr<LLPerfStats::RecordSceneTime>; + +template <typename T> +static inline void trackAttachments(const T * vobj, bool isRigged, RATptr* ratPtrp) +{ + if( !vobj ){ ratPtrp->reset(); return;}; + + const T* rootAtt{vobj}; + if (rootAtt->isAttachment()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + + while( !rootAtt->isRootEdit() ) + { + rootAtt = (T*)(rootAtt->getParent()); + } + + auto avPtr = (T*)(rootAtt->getParent()); + if(!avPtr){ratPtrp->reset(); return;} + + auto& av = avPtr->getID(); + auto& obj = rootAtt->getAttachmentItemID(); + if (!*ratPtrp || (*ratPtrp)->stat.objID != obj || (*ratPtrp)->stat.avID != av) + { + if (*ratPtrp) + { + // deliberately reset to ensure destruction before construction of replacement. + ratPtrp->reset(); + }; + *ratPtrp = std::make_unique<LLPerfStats::RecordAttachmentTime>( + av, + obj, + ( LLPipeline::sShadowRender?LLPerfStats::StatType_t::RENDER_SHADOWS : LLPerfStats::StatType_t::RENDER_GEOMETRY ), + isRigged, + rootAtt->isHUDAttachment()); + } + } + return; +}; + +#endif diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 054e9530d4..e66fefdd1a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -207,6 +207,7 @@ #include "llstacktrace.h" #include "threadpool.h" +#include "llperfstats.h" #if LL_WINDOWS @@ -1492,6 +1493,8 @@ bool idle_startup() LLViewerParcelAskPlay::getInstance()->loadSettings(); } + gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats)); + // *Note: this is where gWorldMap used to be initialized. // register null callbacks for audio until the audio system is initialized @@ -2251,7 +2254,7 @@ bool idle_startup() if (STATE_CLEANUP == LLStartUp::getStartupState()) { - set_startup_status(1.0, "", ""); + set_startup_status(1.0, "", ""); display_startup(); if (!mBenefitsSuccessfullyInit) @@ -3401,6 +3404,9 @@ bool process_login_success_response() if(!text.empty()) gAgentID.set(text); gDebugInfo["AgentID"] = text; + LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled")); + LLPerfStats::StatsRecorder::setFocusAv(gAgentID); + // Agent id needed for parcel info request in LLUrlEntryParcel // to resolve parcel name. LLUrlEntryParcel::setAgentID(gAgentID); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index bc46a61fb0..161c8ce0da 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -75,6 +75,7 @@ #include "llspellcheck.h" #include "llslurl.h" #include "llstartup.h" +#include "llperfstats.h" // Third party library includes #include <boost/algorithm/string.hpp> @@ -166,6 +167,12 @@ static bool handleSetShaderChanged(const LLSD& newvalue) return true; } +static bool handleShadowDetailChanged(const LLSD& newvalue) +{ + gPipeline.handleShadowDetailChanged(); + return true; +} + static bool handleRenderPerfTestChanged(const LLSD& newvalue) { bool status = !newvalue.asBoolean(); @@ -637,6 +644,66 @@ bool toggle_show_object_render_cost(const LLSD& newvalue) } void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value); + +void handleTargetFPSChanged(const LLSD& newValue) +{ + const auto targetFPS = gSavedSettings.getU32("TargetFPS"); + LLPerfStats::tunables.userTargetFPS = targetFPS; +} + +void handleAutoTuneLockChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getBOOL("AutoTuneLock"); + LLPerfStats::tunables.userAutoTuneLock = newval; +} + +void handleAutoTuneFPSChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getBOOL("AutoTuneFPS"); + LLPerfStats::tunables.userAutoTuneEnabled = newval; + if(newval && LLPerfStats::renderAvatarMaxART_ns == 0) // If we've enabled autotune we override "unlimited" to max + { + gSavedSettings.setF32("RenderAvatarMaxART",log10(LLPerfStats::ART_UNLIMITED_NANOS-1000));//triggers callback to update static var + } +} + +void handleRenderAvatarMaxARTChanged(const LLSD& newValue) +{ + LLPerfStats::tunables.updateRenderCostLimitFromSettings(); +} + +void handleUserTargetDrawDistanceChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getF32("AutoTuneRenderFarClipTarget"); + LLPerfStats::tunables.userTargetDrawDistance = newval; +} + +void handleUserTargetReflectionsChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getS32("UserTargetReflections"); + LLPerfStats::tunables.userTargetReflections = newval; +} + +void handlePerformanceStatsEnabledChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getBOOL("PerfStatsCaptureEnabled"); + LLPerfStats::StatsRecorder::setEnabled(newval); +} +void handleUserImpostorByDistEnabledChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getBOOL("AutoTuneImpostorByDistEnabled"); + LLPerfStats::tunables.userImpostorDistanceTuningEnabled = newval; +} +void handleUserImpostorDistanceChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getF32("AutoTuneImpostorFarAwayDistance"); + LLPerfStats::tunables.userImpostorDistance = newval; +} +void handleFPSTuningStrategyChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getU32("TuningFPSStrategy"); + LLPerfStats::tunables.userFPSTuningStrategy = newval; +} //////////////////////////////////////////////////////////////////////////// LLPointer<LLControlVariable> setting_get_control(LLControlGroup& group, const std::string& setting) @@ -670,153 +737,164 @@ void setting_setup_signal_listener(LLControlGroup& group, const std::string& set void settings_setup_listeners() { setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); - setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); - setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); - setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); - setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); - setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); - setting_setup_signal_listener(gSavedSettings, "OctreeAlphaDistanceFactor", handleRepartition); - setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition); - setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "RenderUseTriStrips", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized); - setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAnisotropic", handleAnisotropicChanged); - setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); - setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAvatarCloth", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAvatarPhysicsLODFactor", handleAvatarPhysicsLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderTerrainLODFactor", handleTerrainLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderTreeLODFactor", handleTreeLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderFlexTimeFactor", handleFlexLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderGamma", handleGammaChanged); - setting_setup_signal_listener(gSavedSettings, "RenderFogRatio", handleFogRatioChanged); - setting_setup_signal_listener(gSavedSettings, "RenderMaxPartCount", handleMaxPartCountChanged); - setting_setup_signal_listener(gSavedSettings, "RenderDynamicLOD", handleRenderDynamicLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderLocalLights", handleRenderLocalLightsChanged); - setting_setup_signal_listener(gSavedSettings, "RenderDebugTextureBind", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaDeferred", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaNonDeferred", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged); - setting_setup_signal_listener(gSavedSettings, "RenderMaxVBOSize", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); + setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeAlphaDistanceFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition); + setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUseTriStrips", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized); + setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAnisotropic", handleAnisotropicChanged); + setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); + setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarCloth", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "WindLightUseAtmosShaders", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarPhysicsLODFactor", handleAvatarPhysicsLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainLODFactor", handleTerrainLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTreeLODFactor", handleTreeLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFlexTimeFactor", handleFlexLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGamma", handleGammaChanged); + setting_setup_signal_listener(gSavedSettings, "RenderFogRatio", handleFogRatioChanged); + setting_setup_signal_listener(gSavedSettings, "RenderMaxPartCount", handleMaxPartCountChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDynamicLOD", handleRenderDynamicLODChanged); + setting_setup_signal_listener(gSavedSettings, "RenderLocalLights", handleRenderLocalLightsChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDebugTextureBind", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaDeferred", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAutoMaskAlphaNonDeferred", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderObjectBump", handleRenderBumpChanged); + setting_setup_signal_listener(gSavedSettings, "RenderMaxVBOSize", handleResetVertexBuffersChanged); setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged); - setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged); - setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged); - setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged); - setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged); - setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged); - setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); - setting_setup_signal_listener(gSavedSettings, "TextureMemory", handleVideoMemoryChanged); - setting_setup_signal_listener(gSavedSettings, "ChatFontSize", handleChatFontSizeChanged); - setting_setup_signal_listener(gSavedSettings, "ChatPersistTime", handleChatPersistTimeChanged); - setting_setup_signal_listener(gSavedSettings, "ConsoleMaxLines", handleConsoleMaxLinesChanged); - setting_setup_signal_listener(gSavedSettings, "UploadBakedTexOld", handleUploadBakedTexOldChanged); - setting_setup_signal_listener(gSavedSettings, "UseOcclusion", handleUseOcclusionChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelMaster", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelSFX", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelUI", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelAmbient", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelMusic", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelMedia", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelVoice", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelDoppler", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelRolloff", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelUnderwaterRolloff", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "MuteAudio", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "MuteMusic", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "MuteMedia", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "MuteVoice", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "MuteAmbient", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "MuteUI", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "RenderVBOEnable", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderUseVAO", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderVBOMappingDisable", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderUseStreamVBO", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "RenderPreferStreamDraw", handleResetVertexBuffersChanged); - setting_setup_signal_listener(gSavedSettings, "WLSkyDetail", handleWLSkyDetailChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "JoystickAxis6", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale6", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone6", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisScale0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisScale1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisScale2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisScale3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisScale4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisScale5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone0", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone1", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone2", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone3", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone4", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone5", handleJoystickChanged); - setting_setup_signal_listener(gSavedSettings, "DebugViews", handleDebugViewsChanged); - setting_setup_signal_listener(gSavedSettings, "UserLogFile", handleLogFileChanged); - setting_setup_signal_listener(gSavedSettings, "RenderHideGroupTitle", handleHideGroupTitleChanged); - setting_setup_signal_listener(gSavedSettings, "HighResSnapshot", handleHighResSnapshotChanged); - setting_setup_signal_listener(gSavedSettings, "EnableVoiceChat", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "PTTCurrentlyEnabled", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "PushToTalkButton", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "PushToTalkToggle", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "VoiceEarLocation", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "VoiceInputAudioDevice", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "VoiceOutputAudioDevice", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelMic", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "LipSyncEnabled", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "VelocityInterpolate", handleVelocityInterpolate); - setting_setup_signal_listener(gSavedSettings, "QAMode", show_debug_menus); - setting_setup_signal_listener(gSavedSettings, "UseDebugMenus", show_debug_menus); - setting_setup_signal_listener(gSavedSettings, "AgentPause", toggle_agent_pause); - setting_setup_signal_listener(gSavedSettings, "ShowNavbarNavigationPanel", toggle_show_navigation_panel); - setting_setup_signal_listener(gSavedSettings, "ShowMiniLocationPanel", toggle_show_mini_location_panel); - setting_setup_signal_listener(gSavedSettings, "ShowObjectRenderingCost", toggle_show_object_render_cost); - setting_setup_signal_listener(gSavedSettings, "ForceShowGrid", handleForceShowGrid); - setting_setup_signal_listener(gSavedSettings, "RenderTransparentWater", handleRenderTransparentWaterChanged); - setting_setup_signal_listener(gSavedSettings, "SpellCheck", handleSpellCheckChanged); - setting_setup_signal_listener(gSavedSettings, "SpellCheckDictionary", handleSpellCheckChanged); - setting_setup_signal_listener(gSavedSettings, "LoginLocation", handleLoginLocationChanged); - setting_setup_signal_listener(gSavedSettings, "DebugAvatarJoints", handleDebugAvatarJointsChanged); - setting_setup_signal_listener(gSavedSettings, "RenderAutoMuteByteLimit", handleRenderAutoMuteByteLimitChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged); + setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged); + setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); + setting_setup_signal_listener(gSavedSettings, "TextureMemory", handleVideoMemoryChanged); + setting_setup_signal_listener(gSavedSettings, "ChatFontSize", handleChatFontSizeChanged); + setting_setup_signal_listener(gSavedSettings, "ChatPersistTime", handleChatPersistTimeChanged); + setting_setup_signal_listener(gSavedSettings, "ConsoleMaxLines", handleConsoleMaxLinesChanged); + setting_setup_signal_listener(gSavedSettings, "UploadBakedTexOld", handleUploadBakedTexOldChanged); + setting_setup_signal_listener(gSavedSettings, "UseOcclusion", handleUseOcclusionChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMaster", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelSFX", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelUI", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelAmbient", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMusic", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMedia", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelVoice", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelDoppler", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelRolloff", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelUnderwaterRolloff", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteAudio", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteMusic", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteMedia", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteVoice", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteAmbient", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "MuteUI", handleAudioVolumeChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVBOEnable", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUseVAO", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVBOMappingDisable", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderUseStreamVBO", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "RenderPreferStreamDraw", handleResetVertexBuffersChanged); + setting_setup_signal_listener(gSavedSettings, "WLSkyDetail", handleWLSkyDetailChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "JoystickAxis6", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisScale6", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "FlycamAxisDeadZone6", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisScale5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "AvatarAxisDeadZone5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisScale5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone0", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone1", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone2", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone3", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone4", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "BuildAxisDeadZone5", handleJoystickChanged); + setting_setup_signal_listener(gSavedSettings, "DebugViews", handleDebugViewsChanged); + setting_setup_signal_listener(gSavedSettings, "UserLogFile", handleLogFileChanged); + setting_setup_signal_listener(gSavedSettings, "RenderHideGroupTitle", handleHideGroupTitleChanged); + setting_setup_signal_listener(gSavedSettings, "HighResSnapshot", handleHighResSnapshotChanged); + setting_setup_signal_listener(gSavedSettings, "EnableVoiceChat", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "PTTCurrentlyEnabled", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "PushToTalkButton", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "PushToTalkToggle", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VoiceEarLocation", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VoiceInputAudioDevice", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VoiceOutputAudioDevice", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "AudioLevelMic", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "LipSyncEnabled", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "VelocityInterpolate", handleVelocityInterpolate); + setting_setup_signal_listener(gSavedSettings, "QAMode", show_debug_menus); + setting_setup_signal_listener(gSavedSettings, "UseDebugMenus", show_debug_menus); + setting_setup_signal_listener(gSavedSettings, "AgentPause", toggle_agent_pause); + setting_setup_signal_listener(gSavedSettings, "ShowNavbarNavigationPanel", toggle_show_navigation_panel); + setting_setup_signal_listener(gSavedSettings, "ShowMiniLocationPanel", toggle_show_mini_location_panel); + setting_setup_signal_listener(gSavedSettings, "ShowObjectRenderingCost", toggle_show_object_render_cost); + setting_setup_signal_listener(gSavedSettings, "ForceShowGrid", handleForceShowGrid); + setting_setup_signal_listener(gSavedSettings, "RenderTransparentWater", handleRenderTransparentWaterChanged); + setting_setup_signal_listener(gSavedSettings, "SpellCheck", handleSpellCheckChanged); + setting_setup_signal_listener(gSavedSettings, "SpellCheckDictionary", handleSpellCheckChanged); + setting_setup_signal_listener(gSavedSettings, "LoginLocation", handleLoginLocationChanged); + setting_setup_signal_listener(gSavedSettings, "DebugAvatarJoints", handleDebugAvatarJointsChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAutoMuteByteLimit", handleRenderAutoMuteByteLimitChanged); + + setting_setup_signal_listener(gSavedSettings, "TargetFPS", handleTargetFPSChanged); + setting_setup_signal_listener(gSavedSettings, "AutoTuneFPS", handleAutoTuneFPSChanged); + setting_setup_signal_listener(gSavedSettings, "AutoTuneLock", handleAutoTuneLockChanged); + setting_setup_signal_listener(gSavedSettings, "RenderAvatarMaxART", handleRenderAvatarMaxARTChanged); + setting_setup_signal_listener(gSavedSettings, "PerfStatsCaptureEnabled", handlePerformanceStatsEnabledChanged); + setting_setup_signal_listener(gSavedSettings, "UserTargetReflections", handleUserTargetReflectionsChanged); + setting_setup_signal_listener(gSavedSettings, "AutoTuneRenderFarClipTarget", handleUserTargetDrawDistanceChanged); + setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorFarAwayDistance", handleUserImpostorDistanceChanged); + setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorByDistEnabled", handleUserImpostorByDistEnabledChanged); + setting_setup_signal_listener(gSavedSettings, "TuningFPSStrategy", handleFPSTuningStrategyChanged); setting_setup_signal_listener(gSavedPerAccountSettings, "AvatarHoverOffsetZ", handleAvatarHoverOffsetChanged); } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index bc0fafb29f..a1773ae8d5 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -78,6 +78,7 @@ #include "llscenemonitor.h" #include "llenvironment.h" +#include "llperfstats.h" extern LLPointer<LLViewerTexture> gStartTexture; extern bool gShiftFrame; @@ -256,7 +257,8 @@ static LLTrace::BlockTimerStatHandle FTM_EEP_UPDATE("Env Update"); // Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { - LL_RECORD_BLOCK_TIME(FTM_RENDER); + LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_DISPLAY); // render time capture - This is the main stat for overall rendering. + LL_RECORD_BLOCK_TIME(FTM_RENDER); if (gWindowResized) { //skip render on frames where window has been resized @@ -1049,7 +1051,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) void render_hud_attachments() { - gGL.matrixMode(LLRender::MM_PROJECTION); + LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_HUDS); // render time capture - Primary contributor to HUDs (though these end up in render batches) + gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); @@ -1240,7 +1243,8 @@ bool setup_hud_matrices(const LLRect& screen_region) void render_ui(F32 zoom_factor, int subfield) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); + LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_UI ); // render time capture - Primary UI stat can have HUD time overlap (TODO) + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); LLGLState::checkStates(); @@ -1323,7 +1327,8 @@ static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap"); void swap() { - LL_RECORD_BLOCK_TIME(FTM_SWAP); + LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_SWAP ); // render time capture - Swap buffer time - can signify excessive data transfer to/from GPU + LL_RECORD_BLOCK_TIME(FTM_SWAP); if (gDisplaySwapBuffers) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 06a6c5e373..da9f83905a 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -108,9 +108,11 @@ #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindinglinksets.h" #include "llfloaterpay.h" +#include "llfloaterperformance.h" #include "llfloaterperms.h" #include "llfloaterpostprocess.h" #include "llfloaterpreference.h" +#include "llfloaterpreferencesgraphicsadvanced.h" #include "llfloaterpreferenceviewadvanced.h" #include "llfloaterpreviewtrash.h" #include "llfloaterprofile.h" @@ -314,6 +316,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("pathfinding_linksets", "floater_pathfinding_linksets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingLinksets>); LLFloaterReg::add("pathfinding_console", "floater_pathfinding_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingConsole>); LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); + LLFloaterReg::add("performance", "floater_performance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerformance>); LLFloaterReg::add("perms_default", "floater_perms_default.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPermsDefault>); LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index f3b0e82b3a..489f90aabb 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -55,6 +55,7 @@ #include "m3math.h" #include "m4math.h" #include "llmatrix4a.h" +#include "llperfstats.h" #if !LL_DARWIN && !LL_LINUX extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB; @@ -230,6 +231,16 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) return 0; } + // render time capture + // This path does not appear to have attachments. Prove this then remove. + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; + auto vobj = mFace->getViewerObject(); + if( vobj && vobj->isAttachment() ) + { + trackAttachments( vobj, mFace->isState(LLFace::RIGGED), &ratPtr ); + LL_WARNS("trackAttachments") << "Attachment render time is captuted." << LL_ENDL; + } + U32 triangle_count = 0; S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3573af40cb..68d973dbdc 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3305,6 +3305,8 @@ class LLAvatarCheckImpostorMode : public view_listener_t return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER); case 2: return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER); + case 4: + return (avatar->getVisualMuteSettings() != LLVOAvatar::AV_RENDER_NORMALLY); default: return false; } diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index e5265f1dcd..a440f3232a 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -716,7 +716,7 @@ void LLViewerPartSim::updateSimulation() if (upd && vobj && (vobj->getPCode() == LL_PCODE_VOLUME)) { - if(vobj->getAvatar() && vobj->getAvatar()->isTooComplex()) + if(vobj->getAvatar() && vobj->getAvatar()->isTooComplex() && vobj->getAvatar()->isTooSlowWithShadows()) { upd = FALSE; } diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index a4fbbb3e78..0045dcb547 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -58,6 +58,7 @@ #include "llfeaturemanager.h" #include "llviewernetwork.h" #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived +#include "llperfstats.h" #include "llsdserialize.h" #include "llsdutil.h" #include "llcorehttputil.h" @@ -208,6 +209,13 @@ LLTrace::EventStatHandle<F64Seconds > AVATAR_EDIT_TIME("avataredittime", "Second LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT_RATE("object_cache_hits"); LLTrace::EventStatHandle<F64Seconds > TEXTURE_FETCH_TIME("texture_fetch_time"); + +LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > SCENERY_FRAME_PCT("scenery_frame_pct"); +LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > AVATAR_FRAME_PCT("avatar_frame_pct"); +LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > HUDS_FRAME_PCT("huds_frame_pct"); +LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > UI_FRAME_PCT("ui_frame_pct"); +LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > SWAP_FRAME_PCT("swap_frame_pct"); +LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > IDLE_FRAME_PCT("idle_frame_pct"); } LLViewerStats::LLViewerStats() @@ -414,6 +422,89 @@ void update_statistics() texture_stats_timer.reset(); } } + + if (LLFloaterReg::instanceVisible("scene_load_stats")) + { + static const F32 perf_stats_freq = 1; + static LLFrameTimer perf_stats_timer; + if (perf_stats_timer.getElapsedTimeF32() >= perf_stats_freq) + { + LLStringUtil::format_map_t args; + LLPerfStats::bufferToggleLock.lock(); // prevent toggle for a moment + + auto tot_frame_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FRAME); + // cumulative avatar time (includes idle processing, attachments and base av) + auto tot_avatar_time_raw = LLPerfStats::StatsRecorder::getSum(LLPerfStats::ObjType_t::OT_AVATAR, LLPerfStats::StatType_t::RENDER_COMBINED); + // cumulative avatar render specific time (a bit arbitrary as the processing is too.) + // auto tot_av_idle_time_raw = LLPerfStats::StatsRecorder::getSum(AvType, LLPerfStats::StatType_t::RENDER_IDLE); + // auto tot_avatar_render_time_raw = tot_avatar_time_raw - tot_av_idle_time_raw; + // the time spent this frame on the "display()" call. Treated as "tot time rendering" + auto tot_render_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_DISPLAY); + // sleep time is basically forced sleep when window out of focus + auto tot_sleep_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_SLEEP); + // time spent on UI + auto tot_ui_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_UI); + // cumulative time spent rendering HUDS + auto tot_huds_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_HUDS); + // "idle" time. This is the time spent in the idle poll section of the main loop + auto tot_idle_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_IDLE); + // similar to sleep time, induced by FPS limit + //auto tot_limit_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_FPSLIMIT); + // swap time is time spent in swap buffer + auto tot_swap_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_SWAP); + + LLPerfStats::bufferToggleLock.unlock(); + + auto tot_frame_time_ns = LLPerfStats::raw_to_ns(tot_frame_time_raw); + auto tot_avatar_time_ns = LLPerfStats::raw_to_ns(tot_avatar_time_raw); + auto tot_huds_time_ns = LLPerfStats::raw_to_ns(tot_huds_time_raw); + // UI time includes HUD time so dedut that before we calc percentages + auto tot_ui_time_ns = LLPerfStats::raw_to_ns(tot_ui_time_raw - tot_huds_time_raw); + + // auto tot_sleep_time_ns = LLPerfStats::raw_to_ns( tot_sleep_time_raw ); + // auto tot_limit_time_ns = LLPerfStats::raw_to_ns( tot_limit_time_raw ); + + // auto tot_render_time_ns = LLPerfStats::raw_to_ns( tot_render_time_raw ); + auto tot_idle_time_ns = LLPerfStats::raw_to_ns(tot_idle_time_raw); + auto tot_swap_time_ns = LLPerfStats::raw_to_ns(tot_swap_time_raw); + auto tot_scene_time_ns = LLPerfStats::raw_to_ns(tot_render_time_raw - tot_avatar_time_raw - tot_swap_time_raw - tot_ui_time_raw); + // auto tot_overhead_time_ns = LLPerfStats::raw_to_ns( tot_frame_time_raw - tot_render_time_raw - tot_idle_time_raw ); + + // // remove time spent sleeping for fps limit or out of focus. + // tot_frame_time_ns -= tot_limit_time_ns; + // tot_frame_time_ns -= tot_sleep_time_ns; + + if (tot_frame_time_ns != 0) + { + auto pct_avatar_time = (tot_avatar_time_ns * 100) / tot_frame_time_ns; + auto pct_huds_time = (tot_huds_time_ns * 100) / tot_frame_time_ns; + auto pct_ui_time = (tot_ui_time_ns * 100) / tot_frame_time_ns; + auto pct_idle_time = (tot_idle_time_ns * 100) / tot_frame_time_ns; + auto pct_swap_time = (tot_swap_time_ns * 100) / tot_frame_time_ns; + auto pct_scene_render_time = (tot_scene_time_ns * 100) / tot_frame_time_ns; + pct_avatar_time = llclamp(pct_avatar_time, 0., 100.); + pct_huds_time = llclamp(pct_huds_time, 0., 100.); + pct_ui_time = llclamp(pct_ui_time, 0., 100.); + pct_idle_time = llclamp(pct_idle_time, 0., 100.); + pct_swap_time = llclamp(pct_swap_time, 0., 100.); + pct_scene_render_time = llclamp(pct_scene_render_time, 0., 100.); + if (tot_sleep_time_raw == 0) + { + sample(LLStatViewer::SCENERY_FRAME_PCT, (U32)llround(pct_scene_render_time)); + sample(LLStatViewer::AVATAR_FRAME_PCT, (U32)llround(pct_avatar_time)); + sample(LLStatViewer::HUDS_FRAME_PCT, (U32)llround(pct_huds_time)); + sample(LLStatViewer::UI_FRAME_PCT, (U32)llround(pct_ui_time)); + sample(LLStatViewer::SWAP_FRAME_PCT, (U32)llround(pct_swap_time)); + sample(LLStatViewer::IDLE_FRAME_PCT, (U32)llround(pct_idle_time)); + } + } + else + { + LL_WARNS("performance") << "Scene time 0. Skipping til we have data." << LL_ENDL; + } + perf_stats_timer.reset(); + } + } } void update_texture_time() @@ -524,6 +615,7 @@ void send_viewer_stats(bool include_preferences) system["gpu"] = gpu_desc; system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass(); + system["gpu_memory_bandwidth"] = LLFeatureManager::getInstance()->getGPUMemoryBandwidth(); system["gpu_vendor"] = gGLManager.mGLVendorShort; system["gpu_version"] = gGLManager.mDriverVersionVendorString; system["opengl_version"] = gGLManager.mGLVersionString; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index da3c860ddb..c694db6f7d 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -204,8 +204,8 @@ static std::string get_texture_list_name() void LLViewerTextureList::doPrefetchImages() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - gTextureTimer.start(); - gTextureTimer.pause(); + gTextureTimer.start(); + gTextureTimer.pause(); if (LLAppViewer::instance()->getPurgeCache()) { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 42550ed48d..776223da9d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -113,6 +113,8 @@ #include "llrendersphere.h" #include "llskinningutil.h" +#include "llperfstats.h" + #include <boost/lexical_cast.hpp> extern F32 SPEED_ADJUST_MAX; @@ -2544,12 +2546,19 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL; return; } + // record time and refresh "tooSlow" status + LLPerfStats::RecordAvatarTime T(getID(), LLPerfStats::StatType_t::RENDER_IDLE); // per avatar "idle" time. + updateTooSlow(); static LLCachedControl<bool> disable_all_render_types(gSavedSettings, "DisableAllRenderTypes"); if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)) && !disable_all_render_types && !isSelf()) { - return; + if (!mIsControlAvatar) + { + idleUpdateNameTag( mLastRootPos ); + } + return; } // Update should be happening max once per frame. @@ -3128,7 +3137,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() LLPartData::LL_PART_TARGET_POS_MASK ); // do not generate particles for dummy or overly-complex avatars - if (!mIsDummy && !isTooComplex()) + if (!mIsDummy && !isTooComplex() && !isTooSlowWithShadows()) { setParticleSource(particle_parameters, getID()); } @@ -3213,11 +3222,9 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) static LLCachedControl<F32> FADE_DURATION(gSavedSettings, "RenderNameFadeDuration"); // seconds static LLCachedControl<bool> use_chat_bubbles(gSavedSettings, "UseChatBubbles"); - bool visible_avatar = isVisible() || mNeedsAnimUpdate; bool visible_chat = use_chat_bubbles && (mChats.size() || mTyping); bool render_name = visible_chat || - (visible_avatar && - ((sRenderName == RENDER_NAME_ALWAYS) || + (((sRenderName == RENDER_NAME_ALWAYS) || (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); // If it's your own avatar, don't draw in mouselook, and don't // draw if we're specifically hiding our own name. @@ -3711,7 +3718,7 @@ bool LLVOAvatar::isVisuallyMuted() } else { - muted = isTooComplex(); + muted = isTooComplex() || isTooSlowWithShadows(); } } @@ -8281,6 +8288,94 @@ bool LLVOAvatar::isTooComplex() const return too_complex; } +// use Avatar Render Time as complexity metric +// markARTStale - Mark stale and set the frameupdate to now so that we can wait at least one frame to get a revised number. +void LLVOAvatar::markARTStale() +{ + mARTStale=true; + mLastARTUpdateFrame = LLFrameTimer::getFrameCount(); +} + +// Udpate Avatar state based on render time +void LLVOAvatar::updateTooSlow() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; + static LLCachedControl<bool> alwaysRenderFriends(gSavedSettings, "AlwaysRenderFriends"); + static LLCachedControl<bool> allowSelfImpostor(gSavedSettings, "AllowSelfImpostor"); + const auto id = getID(); + + // mTooSlow - Is the avatar flagged as being slow (includes shadow time) + // mTooSlowWithoutShadows - Is the avatar flagged as being slow even with shadows removed. + // mARTStale - the rendertime we have is stale because of an update. We need to force a re-render to re-assess slowness + + if( mARTStale ) + { + if ( LLFrameTimer::getFrameCount() - mLastARTUpdateFrame < 5 ) + { + // LL_INFOS() << this->getFullname() << " marked stale " << LL_ENDL; + // we've not had a chance to update yet (allow a few to be certain a full frame has passed) + return; + } + + mARTStale = false; + mTooSlow = false; + mTooSlowWithoutShadows = false; + // LL_INFOS() << this->getFullname() << " refreshed ART combined = " << mRenderTime << " @ " << mLastARTUpdateFrame << LL_ENDL; + } + + // Either we're not stale or we've updated. + + U64 render_time_raw; + U64 render_geom_time_raw; + + if( !mTooSlow ) + { + // we are fully rendered, so we use the live values + std::lock_guard<std::mutex> lock{LLPerfStats::bufferToggleLock}; + render_time_raw = LLPerfStats::StatsRecorder::get(LLPerfStats::ObjType_t::OT_AVATAR, id, LLPerfStats::StatType_t::RENDER_COMBINED); + render_geom_time_raw = LLPerfStats::StatsRecorder::get(LLPerfStats::ObjType_t::OT_AVATAR, id, LLPerfStats::StatType_t::RENDER_GEOMETRY); + } + else + { + // use the cached values. + render_time_raw = mRenderTime; + render_geom_time_raw = mGeomTime; + } + if( (LLPerfStats::renderAvatarMaxART_ns > 0) && + (LLPerfStats::raw_to_ns(render_time_raw) >= LLPerfStats::renderAvatarMaxART_ns) ) + { + if( !mTooSlow ) // if we were previously not slow (with or without shadows.) + { + // if we weren't capped, we are now + mLastARTUpdateFrame = LLFrameTimer::getFrameCount(); + mRenderTime = render_time_raw; + mGeomTime = render_geom_time_raw; + mARTStale = false; + mTooSlow = true; + } + if(!mTooSlowWithoutShadows) // if we were not previously above the full impostor cap + { + bool render_friend_or_exception = ( alwaysRenderFriends && LLAvatarTracker::instance().isBuddy( id ) ) || + ( getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER ); + if( (!isSelf() || allowSelfImpostor) && !render_friend_or_exception ) + { + // Note: slow rendering Friends still get their shadows zapped. + mTooSlowWithoutShadows = (LLPerfStats::raw_to_ns(render_geom_time_raw) >= LLPerfStats::renderAvatarMaxART_ns); + } + } + } + else + { + // LL_INFOS() << this->getFullname() << " ("<< (combined?"combined":"geometry") << ") good render time = " << LLPerfStats::raw_to_ns(render_time_raw) << " vs ("<< LLVOAvatar::sRenderTimeCap_ns << " set @ " << mLastARTUpdateFrame << LL_ENDL; + mTooSlow = false; + mTooSlowWithoutShadows = false; + } + if(mTooSlow) + { + LLPerfStats::tunedAvatars++; // increment the number of avatars that have been tweaked. + } +} + //----------------------------------------------------------------------------- // findMotion() //----------------------------------------------------------------------------- @@ -10640,7 +10735,8 @@ void LLVOAvatar::accountRenderComplexityForObject( const F32 max_attachment_complexity, LLVOVolume::texture_cost_t& textures, U32& cost, - hud_complexity_list_t& hud_complexity_list) + hud_complexity_list_t& hud_complexity_list, + object_complexity_list_t& object_complexity_list) { if (attached_object && !attached_object->isHUDAttachment()) { @@ -10698,6 +10794,15 @@ void LLVOAvatar::accountRenderComplexityForObject( << LL_ENDL; // Limit attachment complexity to avoid signed integer flipping of the wearer's ACI cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity); + + if (isSelf()) + { + LLObjectComplexity object_complexity; + object_complexity.objectName = attached_object->getAttachmentItemName(); + object_complexity.objectId = attached_object->getAttachmentItemID(); + object_complexity.objectCost = attachment_total_cost; + object_complexity_list.push_back(object_complexity); + } } } } @@ -10784,6 +10889,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() U32 cost = VISUAL_COMPLEXITY_UNKNOWN; LLVOVolume::texture_cost_t textures; hud_complexity_list_t hud_complexity_list; + object_complexity_list_t object_complexity_list; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { @@ -10827,7 +10933,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() if (volp && !volp->isAttachment()) { accountRenderComplexityForObject(volp, max_attachment_complexity, - textures, cost, hud_complexity_list); + textures, cost, hud_complexity_list, object_complexity_list); } } @@ -10843,7 +10949,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() { const LLViewerObject* attached_object = attachment_iter->get(); accountRenderComplexityForObject(attached_object, max_attachment_complexity, - textures, cost, hud_complexity_list); + textures, cost, hud_complexity_list, object_complexity_list); } } @@ -10908,7 +11014,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() { // Avatar complexity LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity); - + LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list); // HUD complexity LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list); } @@ -11083,7 +11189,7 @@ LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const { // Always want to see this AV as an impostor result = AOA_JELLYDOLL; } - else if (isTooComplex()) + else if (isTooComplex() || isTooSlowWithShadows()) { result = AOA_JELLYDOLL; } @@ -11110,7 +11216,7 @@ void LLVOAvatar::calcMutedAVColor() new_color = LLColor4::grey4; change_msg = " blocked: color is grey4"; } - else if (!isTooComplex()) + else if (!isTooComplex() && !isTooSlowWithShadows()) { new_color = LLColor4::white; change_msg = " simple imposter "; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 8d1dcbcda2..a27327d8a3 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -297,7 +297,8 @@ public: const F32 max_attachment_complexity, LLVOVolume::texture_cost_t& textures, U32& cost, - hud_complexity_list_t& hud_complexity_list); + hud_complexity_list_t& hud_complexity_list, + object_complexity_list_t& object_complexity_list); void calculateUpdateRenderComplexity(); static const U32 VISUAL_COMPLEXITY_UNKNOWN; void updateVisualComplexity(); @@ -349,6 +350,18 @@ public: //-------------------------------------------------------------------- public: BOOL isFullyLoaded() const; + + // check and return current state relative to limits + // default will test only the geometry (combined=false). + // this allows us to disable shadows separately on complex avatars. + inline bool isTooSlowWithShadows() const {return mTooSlow;}; + inline bool isTooSlowWithoutShadows() const {return mTooSlowWithoutShadows;}; + inline bool isTooSlow(bool combined = false) const + { + return(combined?mTooSlow:mTooSlowWithoutShadows); + } + void updateTooSlow(); + bool isTooComplex() const; bool visualParamWeightsAreDefault(); virtual bool getIsCloud() const; @@ -368,6 +381,7 @@ public: void logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed); void calcMutedAVColor(); + void markARTStale(); protected: LLViewerStats::PhaseMap& getPhases() { return mPhases; } @@ -389,6 +403,15 @@ private: LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; + U32 mLastARTUpdateFrame{0}; + U64 mRenderTime{0}; + U64 mGeomTime{0}; + bool mARTStale{true}; + bool mARTCapped{false}; + // variables to hold "slowness" status + bool mTooSlow{false}; + bool mTooSlowWithoutShadows{false}; + private: LLViewerStats::PhaseMap mPhases; @@ -1144,6 +1167,8 @@ public: // COF version of last appearance message received for this av. S32 mLastUpdateReceivedCOFVersion; + U64 getLastART() const { return mRenderTime; } + /** Diagnostics ** ** *******************************************************************************/ diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e923115c43..5e2269893d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -88,6 +88,7 @@ #include "llcallstack.h" #include "llsculptidsize.h" #include "llavatarappearancedefines.h" +#include "llperfstats.h" const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; @@ -5629,6 +5630,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LL_PROFILE_ZONE_NAMED("rebuildGeom - face list"); //get all the faces into a list + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { @@ -5660,6 +5662,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) continue; } + if(vobj->isAttachment()) + { + trackAttachments( vobj, drawablep->isState(LLDrawable::RIGGED),&ratPtr); + } + LLVolume* volume = vobj->getVolume(); if (volume) { @@ -6050,6 +6057,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) U32 buffer_count = 0; + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr{}; for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); @@ -6059,6 +6067,11 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVOVolume* vobj = drawablep->getVOVolume(); if (!vobj) continue; + + if (vobj->isAttachment()) + { + trackAttachments( vobj, drawablep->isState(LLDrawable::RIGGED), &ratPtr ); + } if (debugLoggingEnabled("AnimatedObjectsLinkset")) { @@ -6508,10 +6521,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace U32 indices_index = 0; U16 index_offset = 0; - while (face_iter < i) + std::unique_ptr<LLPerfStats::RecordAttachmentTime> ratPtr; + while (face_iter < i) { //update face indices for new buffer facep = *face_iter; + LLViewerObject* vobj = facep->getViewerObject(); + if(vobj && vobj->isAttachment()) + { + trackAttachments(vobj, LLPipeline::sShadowRender, &ratPtr); + } if (buffer.isNull()) { // Bulk allocation failed diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index aa32ef04b2..575a3666d7 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -33,6 +33,7 @@ #include "llstl.h" #include "llagent.h" +#include "llagentcamera.h" #include "llviewercontrol.h" #include "lldrawpool.h" #include "llglheaders.h" @@ -1407,6 +1408,32 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi } } +S32 LLWorld::getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_avs) +{ + static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64); + S32 nearby_max_complexity = 0; + F32 radius = render_far_clip * render_far_clip; + std::vector<LLCharacter*>::iterator char_iter = LLCharacter::sInstances.begin(); + while (char_iter != LLCharacter::sInstances.end()) + { + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter); + if (avatar && !avatar->isDead() && !avatar->isControlAvatar()) + { + if ((dist_vec_squared(avatar->getPositionGlobal(), gAgent.getPositionGlobal()) > radius) && + (dist_vec_squared(avatar->getPositionGlobal(), gAgentCamera.getCameraPositionGlobal()) > radius)) + { + char_iter++; + continue; + } + avatar->calculateUpdateRenderComplexity(); + nearby_max_complexity = llmax(nearby_max_complexity, (S32)avatar->getVisualComplexity()); + valid_nearby_avs.push_back(*char_iter); + } + char_iter++; + } + return nearby_max_complexity; +} + bool LLWorld::isRegionListed(const LLViewerRegion* region) const { region_list_t::const_iterator it = find(mRegionList.begin(), mRegionList.end(), region); diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index 5c43cdf4e2..68db2b8ccf 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -51,6 +51,7 @@ class LLHost; class LLViewerObject; class LLSurfacePatch; +class LLCharacter; class LLCloudPuff; class LLCloudGroup; class LLVOAvatar; @@ -174,6 +175,8 @@ public: // or if the circuit to this simulator had been lost. bool isRegionListed(const LLViewerRegion* region) const; + S32 getNearbyAvatarsAndCompl(std::vector<LLCharacter*> &valid_nearby_avs); + private: region_list_t mActiveRegionList; region_list_t mRegionList; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 96ba80dacc..500cea98fb 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -43,6 +43,7 @@ #include "llui.h" #include "llglheaders.h" #include "llrender.h" +#include "llstartup.h" #include "llwindow.h" // swapBuffers() // newview includes @@ -149,6 +150,7 @@ U32 LLPipeline::RenderFSAASamples; U32 LLPipeline::RenderResolutionDivisor; bool LLPipeline::RenderUIBuffer; S32 LLPipeline::RenderShadowDetail; +S32 LLPipeline::RenderShadowSplits; bool LLPipeline::RenderDeferredSSAO; F32 LLPipeline::RenderShadowResolutionScale; bool LLPipeline::RenderLocalLights; @@ -544,6 +546,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); connectRefreshCachedSettingsSafe("RenderUIBuffer"); connectRefreshCachedSettingsSafe("RenderShadowDetail"); + connectRefreshCachedSettingsSafe("RenderShadowSplits"); connectRefreshCachedSettingsSafe("RenderDeferredSSAO"); connectRefreshCachedSettingsSafe("RenderShadowResolutionScale"); connectRefreshCachedSettingsSafe("RenderLocalLights"); @@ -615,7 +618,6 @@ void LLPipeline::init() LLPipeline::~LLPipeline() { - } void LLPipeline::cleanup() @@ -1073,6 +1075,7 @@ void LLPipeline::refreshCachedSettings() RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); + RenderShadowSplits = gSavedSettings.getS32("RenderShadowSplits"); RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO"); RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale"); RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights"); @@ -5990,7 +5993,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) LLDrawable* drawable = light->drawable; const LLViewerObject *vobj = light->drawable->getVObj(); if(vobj && vobj->getAvatar() - && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()) + && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList() || vobj->getAvatar()->isTooSlowWithShadows()) ) { drawable->clearState(LLDrawable::NEARBY_LIGHT); @@ -6069,7 +6072,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) continue; } LLVOAvatar * av = light->getAvatar(); - if (av && (av->isTooComplex() || av->isInMuteList())) + if (av && (av->isTooComplex() || av->isInMuteList() || av->isTooSlowWithShadows())) { // avatars that are already in the list will be removed by removeMutedAVsLights continue; @@ -10235,14 +10238,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) if (mSunDiffuse == LLColor4::black) { //sun diffuse is totally black, shadows don't matter - LLGLDepthTest depth(GL_TRUE); - - for (S32 j = 0; j < 4; j++) - { - mShadow[j].bindTarget(); - mShadow[j].clear(); - mShadow[j].flush(); - } + skipRenderingShadows(); } else { @@ -10297,7 +10293,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) std::vector<LLVector3> fp; - if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir)) + if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir) + || j > RenderShadowSplits) { //no possible shadow receivers if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) @@ -10859,10 +10856,12 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar) << " is " << ( too_complex ? "" : "not ") << "too complex" << LL_ENDL; - pushRenderTypeMask(); - - if (visually_muted || too_complex) - { + bool too_slow = avatar->isTooSlowWithShadows(); + + pushRenderTypeMask(); + + if ( !too_slow && ( visually_muted || too_complex ) ) + { // only show jelly doll geometry andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, @@ -11502,3 +11501,27 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id ) } } +void LLPipeline::skipRenderingShadows() +{ + LLGLDepthTest depth(GL_TRUE); + + for (S32 j = 0; j < 4; j++) + { + mShadow[j].bindTarget(); + mShadow[j].clear(); + mShadow[j].flush(); + } +} + +void LLPipeline::handleShadowDetailChanged() +{ + if (RenderShadowDetail > gSavedSettings.getS32("RenderShadowDetail")) + { + skipRenderingShadows(); + } + else + { + LLViewerShaderMgr::instance()->setShaders(); + } +} + diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 62d3ae7a39..584d32a767 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -425,6 +425,7 @@ public: void skipRenderingOfTerrain( bool flag ); void hideObject( const LLUUID& id ); void restoreHiddenObject( const LLUUID& id ); + void handleShadowDetailChanged(); private: void unloadShaders(); @@ -436,6 +437,7 @@ private: void connectRefreshCachedSettingsSafe(const std::string name); void hideDrawable( LLDrawable *pDrawable ); void unhideDrawable( LLDrawable *pDrawable ); + void skipRenderingShadows(); public: enum {GPU_CLASS_MAX = 3 }; @@ -717,7 +719,6 @@ protected: U64 mOldRenderDebugMask; std::stack<U32> mRenderDebugFeatureStack; - ///////////////////////////////////////////// // // @@ -912,6 +913,7 @@ public: static U32 RenderResolutionDivisor; static bool RenderUIBuffer; static S32 RenderShadowDetail; + static S32 RenderShadowSplits; static bool RenderDeferredSSAO; static F32 RenderShadowResolutionScale; static bool RenderLocalLights; diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index c3ce83e834..c0182eaa14 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -983,6 +983,9 @@ name="OutfitGalleryItemUnselected" value="0.4 0.4 0.4 1" /> <color - name="AddPaymentPanel" + name="PanelGray" value="0.27 0.27 0.27 1" /> + <color + name="PerformanceMid" + value="1 0.8 0 1" /> </colors> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 4429a1677e..ae8c451a90 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -150,6 +150,7 @@ with the same filename but different name <texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" /> <texture name="Command_Environments_Icon" file_name="toolbar_icons/environments.png" preload="true" /> <texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" /> + <texture name="Command_Performance_Icon" file_name="toolbar_icons/performance.png" preload="true" /> <texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" /> <texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" /> <texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" /> diff --git a/indra/newview/skins/default/textures/toolbar_icons/performance.png b/indra/newview/skins/default/textures/toolbar_icons/performance.png Binary files differnew file mode 100644 index 0000000000..91baf849c8 --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/performance.png diff --git a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml index 1f980564d4..ac88263aa1 100644 --- a/indra/newview/skins/default/xui/en/floater_add_payment_method.xml +++ b/indra/newview/skins/default/xui/en/floater_add_payment_method.xml @@ -19,7 +19,7 @@ </floater.string> <panel background_opaque="false" - bg_alpha_color="AddPaymentPanel" + bg_alpha_color="PanelGray" border_visible="false" background_visible="true" label="wrapper_panel" diff --git a/indra/newview/skins/default/xui/en/floater_avatar_render_settings.xml b/indra/newview/skins/default/xui/en/floater_avatar_render_settings.xml index e088d4d2a1..d222dca98b 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_render_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_render_settings.xml @@ -10,7 +10,7 @@ save_rect="true" single_instance="true" reuse_instance="true" - title="AVATAR RENDER SETTINGS" + title="AVATAR DISPLAY EXCEPTIONS" width="300"> <string name="av_never_render" @@ -18,53 +18,45 @@ <string name="av_always_render" value="Always"/> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="8" - right="-47" - label="Filter People" - max_length_chars="300" - name="people_filter_input" - text_color="Black" - text_pad_left="10" - top="4" /> - <menu_button - follows="top|right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="7" - menu_filename="menu_avatar_rendering_settings_add.xml" - menu_position="bottomleft" - name="plus_btn" - tool_tip="Actions on selected person" - top="3" - width="31" /> <name_list - bottom="-8" + bottom="-33" draw_heading="true" follows="all" left="8" multi_select="false" name="render_settings_list" right="-8" - top="32"> + top="0"> <name_list.columns label="Name" name="name" - relative_width="0.5" /> + relative_width="0.65" /> <name_list.columns - label="Render setting" + label="Full detail" name="setting" - relative_width="0.25" /> - <name_list.columns - label="Date added" - name="timestamp" - relative_width="0.25" /> + relative_width="0.35" /> </name_list> + <panel + bg_alpha_color="ScrollBgWriteableColor" + background_visible="true" + background_opaque="false" + bevel_style="none" + follows="bottom|left|right" + name="add_subpanel" + layout="topleft" + height="28" + top_pad="0"> + <menu_button + follows="bottom|left" + height="25" + label="Add someone..." + layout="topleft" + menu_filename="menu_avatar_rendering_settings_add.xml" + menu_position="bottomleft" + name="plus_btn" + tool_tip="Actions on selected person" + top="1" + left="8" + width="120" /> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_performance.xml b/indra/newview/skins/default/xui/en/floater_performance.xml new file mode 100644 index 0000000000..ee88701037 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_performance.xml @@ -0,0 +1,367 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + height="642" + layout="topleft" + name="performance" + save_rect="true" + title="IMPROVE GRAPHICS SPEED" + width="580"> + <string + name="fps_text" + value="frames per second"/> + <string + name="max_text" + value=" (maximum)"/> + <panel + bevel_style="none" + follows="left|top" + height="540" + width="580" + name="panel_top" + visible="true" + layout="topleft" + left="0" + top="0"> + <panel + bg_alpha_color="black" + background_visible="true" + background_opaque="false" + border="false" + bevel_style="none" + follows="left|top" + height="40" + width="560" + name="fps_subpanel" + layout="topleft" + left="10" + top="5"> + <text + follows="left|top" + font="SansSerifHuge" + text_color="White" + height="20" + layout="topleft" + left="10" + top="8" + name="fps_value" + width="42"> + 167 + </text> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left_pad="3" + top="13" + name="fps_lbl" + width="450"> + frames per second + </text> + <text + follows="left|top" + text_color="White" + height="20" + layout="topleft" + left="395" + top="7" + name="fps_desc1_lbl" + width="150"> + Allow 5-10 seconds for + </text> + <text + follows="left|top" + text_color="White" + height="20" + layout="topleft" + top_pad="-3" + name="fps_desc2_lbl" + width="150"> + changes to take full effect. + </text> + </panel> + </panel> + <panel + bevel_style="none" + follows="left|top" + height="540" + width="580" + name="panel_performance_main" + visible="true" + layout="topleft" + left="0" + top="60"> + <panel + bg_alpha_color="PanelGray" + background_visible="true" + background_opaque="false" + border="true" + bevel_style="none" + follows="left|top" + height="50" + width="560" + name="settings_subpanel" + layout="topleft" + left="10" + top="5"> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="10" + name="settings_lbl" + top="7" + width="180"> + Graphics settings + </text> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="10" + name="settings_desc" + top_pad="0" + width="395"> + Choose settings for distance, water, lighting and more. + </text> + <icon + height="16" + width="16" + image_name="Arrow_Right_Off" + mouse_opaque="true" + name="icon_arrow3" + follows="right|top" + top="19" + right="-20"/> + </panel> + <panel + bg_alpha_color="PanelGray" + background_visible="true" + background_opaque="false" + border="true" + bevel_style="none" + follows="left|top" + height="50" + width="560" + name="nearby_subpanel" + layout="topleft" + top_pad="10"> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="10" + name="avatars_nearby_lbl" + top="7" + width="205"> + Avatars nearby + </text> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="10" + name="avatars_nearby_desc" + top_pad="0" + width="395"> + Manage which nearby avatars are fully displayed. + </text> + <icon + height="16" + width="16" + image_name="Arrow_Right_Off" + mouse_opaque="true" + name="icon_arrow2" + follows="right|top" + top="19" + right="-20"/> + </panel> + <panel + bg_alpha_color="PanelGray" + background_visible="true" + background_opaque="false" + border="true" + bevel_style="none" + follows="left|top" + height="50" + width="560" + name="complexity_subpanel" + layout="topleft" + top_pad="10"> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="10" + name="complexity_lbl" + top="7" + width="180"> + Your avatar complexity + </text> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="10" + name="complexity_info" + top_pad="0" + width="455"> + Reduce the complexity of your avatar if you aren't satisfied with current FPS. + </text> + <icon + height="16" + width="16" + image_name="Arrow_Right_Off" + mouse_opaque="true" + name="icon_arrow4" + follows="right|top" + top="19" + right="-20"/> + </panel> + <panel + bg_alpha_color="PanelGray" + background_visible="true" + background_opaque="false" + border="true" + bevel_style="none" + follows="left|top" + height="50" + width="560" + name="huds_subpanel" + layout="topleft" + top_pad="10"> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="10" + name="huds_lbl" + top="7" + width="135"> + Your active HUDs + </text> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="10" + name="huds_desc" + top_pad="0" + width="395"> + Removing HUDs you are not using can improve speed. + </text> + <icon + height="16" + width="16" + image_name="Arrow_Right_Off" + mouse_opaque="true" + name="icon_arrow4" + follows="right|top" + top="19" + right="-20"/> + </panel> + <panel + bg_alpha_color="PanelGray" + background_visible="true" + background_opaque="false" + border="true" + bevel_style="none" + follows="left|top" + height="50" + width="560" + name="autoadjustments_subpanel" + layout="topleft" + top_pad="10"> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="10" + name="auto_adj_lbl" + top="7" + width="175"> + Preferred frame rate + </text> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="10" + name="auto_adj_desc" + top_pad="0" + width="485"> + Allow automatic adjustments to reach your preferred frame rate (advanced). + </text> + <icon + height="16" + width="16" + image_name="Arrow_Right_Off" + mouse_opaque="true" + name="icon_arrow4" + follows="right|top" + top="19" + right="-20"/> + </panel> + </panel> + <panel + filename="panel_performance_nearby.xml" + follows="all" + layout="topleft" + left="0" + name="panel_performance_nearby" + visible="false" + top="55" /> + <panel + filename="panel_performance_complexity.xml" + follows="all" + layout="topleft" + left="0" + name="panel_performance_complexity" + visible="false" + top="55" /> + <panel + filename="panel_performance_preferences.xml" + follows="all" + layout="topleft" + left="0" + name="panel_performance_preferences" + visible="false" + top="55" /> + <panel + filename="panel_performance_huds.xml" + follows="all" + layout="topleft" + left="0" + name="panel_performance_huds" + visible="false" + top="55" /> + <panel + filename="panel_performance_autoadjustments.xml" + follows="all" + layout="topleft" + left="0" + name="panel_performance_autoadjustments" + visible="false" + top="55" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index d1e167df64..9da6ec093b 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -39,7 +39,8 @@ max_val="512" name="DrawDistance" top_delta="16" - width="330" /> + width="330"> + </slider> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml index 2abd8ec5c0..37efbe654e 100644 --- a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml @@ -410,6 +410,59 @@ </stat_view> </stat_view> </stat_view> + <stat_view + name="frame_stats" + label="Frame breakdown" + show_label="true"> + <stat_bar name="packet_loss" + label="Scenery" + orientation="horizontal" + unit_label=" %" + stat="scenery_frame_pct" + bar_max="100" + tick_spacing="0.5" + show_bar="false"/> + <stat_bar name="packet_loss" + label="Avatar" + orientation="horizontal" + unit_label=" %" + stat="avatar_frame_pct" + bar_max="100" + tick_spacing="0.5" + show_bar="false"/> + <stat_bar name="packet_loss" + label="UI" + orientation="horizontal" + unit_label=" %" + stat="ui_frame_pct" + bar_max="100" + tick_spacing="0.5" + show_bar="false"/> + <stat_bar name="packet_loss" + label="HUDs" + orientation="horizontal" + unit_label=" %" + stat="huds_frame_pct" + bar_max="100" + tick_spacing="0.5" + show_bar="false"/> + <stat_bar name="packet_loss" + label="Swap" + orientation="horizontal" + unit_label=" %" + stat="swap_frame_pct" + bar_max="100" + tick_spacing="0.5" + show_bar="false"/> + <stat_bar name="packet_loss" + label="Tasks" + orientation="horizontal" + unit_label=" %" + stat="idle_frame_pct" + bar_max="100" + tick_spacing="0.5" + show_bar="false"/> + </stat_view> </container_view> </scroll_container> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index 7ad692038e..22006c287f 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -131,22 +131,12 @@ <menu_item_separator /> <context_menu - label="Render Avatar" + label="Display this avatar" layout="topleft" - name="Render Avatar"> - <menu_item_check - name="RenderNormally" - label="Default"> - <menu_item_check.on_check - function="Avatar.CheckImpostorMode" - parameter="0" /> - <menu_item_check.on_click - function="Avatar.SetImpostorMode" - parameter="0" /> - </menu_item_check> + name="Render Avatar"> <menu_item_check name="AlwaysRenderFully" - label="Always"> + label="Always full detail"> <menu_item_check.on_check function="Avatar.CheckImpostorMode" parameter="2" /> @@ -156,7 +146,7 @@ </menu_item_check> <menu_item_check name="DoNotRender" - label="Never"> + label="Never full detail"> <menu_item_check.on_check function="Avatar.CheckImpostorMode" parameter="1" /> @@ -164,6 +154,16 @@ function="Avatar.SetImpostorMode" parameter="1" /> </menu_item_check> + <menu_item_call + name="RenderNormally" + label="Remove from exceptions"> + <menu_item_call.on_visible + function="Avatar.CheckImpostorMode" + parameter="4" /> + <menu_item_call.on_click + function="Avatar.SetImpostorMode" + parameter="0" /> + </menu_item_call> <menu_item_separator /> <menu_item_call label="Exceptions..." diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml index acbb9b860d..665eb9a82f 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -122,39 +122,39 @@ <menu_item_separator /> <context_menu - label="Render Avatar" + label="Display this avatar" layout="topleft" - name="Render Avatar"> - <menu_item_check - name="RenderNormally" - label="Default"> - <menu_item_check.on_check - function="Avatar.CheckImpostorMode" - parameter="0" /> - <menu_item_check.on_click - function="Avatar.SetImpostorMode" - parameter="0" /> - </menu_item_check> - <menu_item_check - name="AlwaysRenderFully" - label="Always"> - <menu_item_check.on_check - function="Avatar.CheckImpostorMode" - parameter="2" /> - <menu_item_check.on_click - function="Avatar.SetImpostorMode" - parameter="2" /> - </menu_item_check> - <menu_item_check - name="DoNotRender" - label="Never"> - <menu_item_check.on_check - function="Avatar.CheckImpostorMode" - parameter="1" /> - <menu_item_check.on_click - function="Avatar.SetImpostorMode" - parameter="1" /> - </menu_item_check> + name="Render Avatar"> + <menu_item_check + name="AlwaysRenderFully" + label="Always full detail"> + <menu_item_check.on_check + function="Avatar.CheckImpostorMode" + parameter="2" /> + <menu_item_check.on_click + function="Avatar.SetImpostorMode" + parameter="2" /> + </menu_item_check> + <menu_item_check + name="DoNotRender" + label="Never full detail"> + <menu_item_check.on_check + function="Avatar.CheckImpostorMode" + parameter="1" /> + <menu_item_check.on_click + function="Avatar.SetImpostorMode" + parameter="1" /> + </menu_item_check> + <menu_item_call + name="RenderNormally" + label="Remove from exceptions"> + <menu_item_call.on_visible + function="Avatar.CheckImpostorMode" + parameter="4" /> + <menu_item_call.on_click + function="Avatar.SetImpostorMode" + parameter="0" /> + </menu_item_call> <menu_item_separator /> <menu_item_call label="Exceptions..." diff --git a/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings.xml b/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings.xml index 5163cd3115..1a18483418 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings.xml @@ -3,24 +3,25 @@ layout="topleft" name="Settings"> <menu_item_check - label="Default" - layout="topleft" - name="default"> - <on_click function="Settings.SetRendering" parameter="default"/> - <on_check function="Settings.IsSelected" parameter="default" /> - </menu_item_check> - <menu_item_check - label="Always render" + label="Always full detail" layout="topleft" name="always_render"> <on_click function="Settings.SetRendering" parameter="always"/> - <on_check function="Settings.IsSelected" parameter="always" /> + <on_check function="Settings.IsSelected" parameter="always" /> </menu_item_check> <menu_item_check - label="Never render" + label="Never full detail" layout="topleft" name="never_render"> <on_click function="Settings.SetRendering" parameter="never"/> - <on_check function="Settings.IsSelected" parameter="never" /> - </menu_item_check> + <on_check function="Settings.IsSelected" parameter="never" /> + </menu_item_check> + <menu_item_check + label="Remove from exceptions" + layout="topleft" + name="default"> + <on_click function="Settings.SetRendering" parameter="default"/> + <on_check function="Settings.IsSelected" parameter="default" /> + <on_visible function="Settings.IsSelected" parameter="non_default" /> + </menu_item_check> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings_add.xml b/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings_add.xml index c64b24ed70..6e09eb5981 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings_add.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_rendering_settings_add.xml @@ -4,13 +4,13 @@ left="0" bottom="0" visible="false" mouse_opaque="false"> <menu_item_call - label="Always Render a Resident..." + label="Always full detail..." name="add_avatar_always_render"> <on_click function="Settings.AddNewEntry" parameter="always"/> </menu_item_call> <menu_item_call - label="Never Render a Resident..." + label="Never full detail..." name="add_avatar_never_render"> <on_click function="Settings.AddNewEntry" parameter="never"/> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 58584345a9..f72d1f0bf9 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -862,7 +862,16 @@ parameter="UseDebugMenus" /> </menu_item_check> </menu> - + <menu_item_check + label="Improve graphics speed..." + name="Performance"> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="performance" /> + <menu_item_check.on_check + function="Floater.Visible" + parameter="performance" /> + </menu_item_check> <menu_item_separator/> <!-- <menu_item_check label="Show Navigation Bar" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1ddec93668..03f9c9ce97 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1900,6 +1900,41 @@ Graphics Quality can be raised in Preferences > Graphics. <notification icon="alertmodal.tga" + name="AutoFPSConfirmDisable" + type="alertmodal"> +Changing this setting will disable automatic adjustment and turn off 'Automatic settings'. +Are you sure you want to continue? + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="Continue"/> + </notification> + <notification + icon="alertmodal.tga" + name="AdvancedLightingConfirm" + type="alertmodal"> +To turn on advanced lighting, we need to increase quality to level 4. + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + <notification + icon="alertmodal.tga" + name="ShadowsConfirm" + type="alertmodal"> +To enable shadows, we need to increase quality to level 4. + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="RegionNoTerraforming" type="alertmodal"> The region [REGION] does not allow terraforming. diff --git a/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml b/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml new file mode 100644 index 0000000000..5d4ffd232b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml @@ -0,0 +1,315 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bevel_style="none" + follows="left|top" + height="580" + width="580" + name="panel_performance_autoadjustments" + layout="topleft" + left="0" + top="0"> + <button + height="16" + width="16" + layout="topleft" + mouse_opaque="true" + follows="left|top" + name="back_btn" + top="7" + image_selected="Arrow_Left_Off" + image_pressed="Arrow_Left_Off" + image_unselected="Arrow_Left_Off" + left="15" + is_toggle="true"> + </button> + <text + follows="left|top" + height="20" + layout="topleft" + left_pad="3" + top="10" + name="back_lbl" + width="40"> + Back + </text> + <text + follows="left|top" + font="SansSerifLarge" + text_color="white" + height="20" + layout="topleft" + left="20" + top_pad="10" + name="settings_title" + width="300"> + Preferred frame rate + </text> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border0" + top_pad="15" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="20" + name="targetfps_desc" + wrap="true" + width="140" + top_pad="20"> + Desired frame rate + </text> + <spinner + name="target_fps" + control_name="TargetFPS" + font="SansSerifLarge" + tool_tip="The viewer will attempt to achieve this by adjusting your graphics settings." + layout="topleft" + follows="right|top" + left_pad="5" + top_delta="0" + height="25" + visible="true" + decimal_digits="0" + increment="1" + initial_value="25" + max_val="300" + min_val="1" + width="48" + label_width="0" /> + <button + control_name="AutoTuneFPS" + follows="top|right" + height="24" + initial_value="false" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Start" + label_selected="Stop" + layout="topleft" + left_pad="10" + name="AutoTuneFPS" + top_delta="-1" + tool_tip="The viewer will attempt to adjust settings to meet the target FPS." + width="72"> + </button> + <check_box + control_name="AutoTuneLock" + follows="top|right" + height="20" + initial_value="true" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Continuous" + layout="topleft" + left_pad="10" + name="AutoTuneContinuous" + top_delta="0" + tool_tip="The viewer will continually adapt the settings to meet the target FPS until stopped even with the floater closed. When disabled clicking the Start button will adjust for the current settings then stop." + width="64"> + </check_box> + <text + follows="left|top" + font="SansSerif" + text_color="White" + height="20" + layout="topleft" + left="20" + name="settings_desc" + top_pad="20" + wrap="true" + width="150"> + Settings affect + </text> + <combo_box + follows="top|left" + font="SansSerif" + height="20" + layout="topleft" + left_pad="15" + control_name="TuningFPSStrategy" + name="TuningFPSStrategy" + width="130"> + <combo_box.item + label="Avatars Only" + name="av_only" + value="0" /> + <combo_box.item + label="Avatars and Scene" + name="av_and_scene" + value="1" /> + </combo_box> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border_vsync" + top_pad="20" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left="20" + top_pad="20" + name="vsync_desc" + width="580"> + Synchronize the refresh rate and frame rate of a monitor, + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="3" + left="20" + name="vsync_desc2" + width="580"> + which can result in smoother performance. + </text> + <check_box + control_name="RenderVSyncEnable" + height="16" + initial_value="true" + label="Enable VSync" + label_text.text_color="White" + layout="topleft" + top_pad="15" + name="vsync" + tool_tip="Enable Vertical synchronization to reduce screen tearing and stuttering." + width="315" /> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border1" + top_pad="20" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left="20" + top_pad="15" + name="simplify_dist_desc" + width="580"> + Reducing detail shown on avatars that are far away will improve graphics speed. + </text> + <check_box + control_name="AutoTuneImpostorByDistEnabled" + height="19" + label="Simplify avatars beyond" + label_text.text_color="White" + layout="topleft" + follows="top|left" + name="AutoTuneImpostorByDistEnabled" + tool_tip="When enabled the viewer will adjust the MaxNonImpostors setting to limit fully rendered avatars to those within the defined radius." + top_pad="15" + width="190" /> + <spinner + control_name="AutoTuneImpostorFarAwayDistance" + height="20" + layout="topleft" + follows="top|left" + name="ffa_autotune" + left_pad="20" + decimal_digits="2" + min_val="16" + max_val="256" + width="60" > + </spinner> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left_pad="10" + name="dist_meters" + width="70"> + meters + </text> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border2" + top_pad="20" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left="20" + top_pad="20" + name="dist_limits_desc" + width="580"> + Choose the distance range that automatic settings will affect. + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="15" + name="min_dist_lbl" + width="120"> + Minimum distance + </text> + <spinner + control_name="AutoTuneRenderFarClipMin" + height="20" + layout="topleft" + left_pad="15" + follows="top|left" + name="min_dd_autotune" + decimal_digits="2" + min_val="32" + max_val="256" + width="60"> + </spinner> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="15" + left="20" + name="pref_dist_lbl" + width="120"> + Maximum distance + </text> + <spinner + control_name="AutoTuneRenderFarClipTarget" + height="20" + layout="topleft" + follows="top|left" + name="pref_dd_autotune" + left_pad="15" + min_val="32" + max_val="256" + width="60"> + </spinner> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_performance_complexity.xml b/indra/newview/skins/default/xui/en/panel_performance_complexity.xml new file mode 100644 index 0000000000..954fd0a8c1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_performance_complexity.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bevel_style="none" + follows="left|top" + height="580" + width="580" + name="panel_performance_complexity" + layout="topleft" + left="0" + top="0"> + <button + height="16" + width="16" + layout="topleft" + mouse_opaque="true" + follows="left|top" + name="back_btn" + top="7" + image_selected="Arrow_Left_Off" + image_pressed="Arrow_Left_Off" + image_unselected="Arrow_Left_Off" + left="15" + is_toggle="true"> + </button> + <text + follows="left|top" + height="20" + layout="topleft" + left_pad="3" + top="10" + name="back_lbl" + width="40"> + Back + </text> + <text + follows="left|top" + font="SansSerifLarge" + text_color="white" + height="20" + layout="topleft" + left="20" + top_pad="10" + name="attachments_title" + width="195"> + Your avatar complexity + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="5" + left="20" + name="attachments_desc1" + width="580"> + Attachments make your avatar more complex. If your avatar is very complex, some other + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="3" + left="20" + name="attachments_desc2" + width="580"> + people may not see you in full detail, and your graphics speed may be reduced. Removing + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="3" + left="20" + name="attachments_desc3" + width="580"> + heavy attachments that you don’t need can help. + </text> + <name_list + column_padding="0" + draw_stripes="true" + height="429" + follows="left|top" + layout="topleft" + name="obj_list" + top_pad="10" + width="540"> + <name_list.columns + label="" + name="complex_visual" + width="90" /> + <name_list.columns + label="" + name="complex_value" + width="40" /> + <name_list.columns + label="" + name="name"/> + </name_list> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_performance_huds.xml b/indra/newview/skins/default/xui/en/panel_performance_huds.xml new file mode 100644 index 0000000000..289f865eb7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_performance_huds.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bevel_style="none" + follows="left|top" + height="580" + width="580" + name="panel_performance_huds" + layout="topleft" + left="0" + top="0"> + <button + height="16" + width="16" + layout="topleft" + mouse_opaque="true" + follows="left|top" + name="back_btn" + top="7" + image_selected="Arrow_Left_Off" + image_pressed="Arrow_Left_Off" + image_unselected="Arrow_Left_Off" + left="15" + is_toggle="true"> + </button> + <text + follows="left|top" + height="20" + layout="topleft" + left_pad="3" + top="10" + name="back_lbl" + width="40"> + Back + </text> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="20" + top_pad="10" + name="huds_title" + width="135"> + Your active HUDs + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="5" + left="20" + name="huds_desc1" + width="540"> + Detaching HUDs you aren't using saves memory and can make Second Life run faster. + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="3" + left="20" + name="huds_desc2" + width="540"> + Note: Using a HUD's minimize button does not detach it. + </text> + <name_list + column_padding="0" + draw_stripes="true" + height="450" + follows="left|top" + layout="topleft" + name="hud_list" + top_pad="10" + width="540"> + <name_list.columns + label="" + name="complex_visual" + width="90" /> + <name_list.columns + label="" + name="complex_value" + width="40" /> + <name_list.columns + label="" + name="name"/> + </name_list> +</panel> + diff --git a/indra/newview/skins/default/xui/en/panel_performance_nearby.xml b/indra/newview/skins/default/xui/en/panel_performance_nearby.xml new file mode 100644 index 0000000000..e80bf592e4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_performance_nearby.xml @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bevel_style="none" + follows="left|top" + height="530" + width="580" + name="panel_performance_nearby" + layout="topleft" + left="0" + top="0"> + <button + height="16" + width="16" + layout="topleft" + mouse_opaque="true" + follows="left|top" + name="back_btn" + top="7" + image_selected="Arrow_Left_Off" + image_pressed="Arrow_Left_Off" + image_unselected="Arrow_Left_Off" + left="15" + is_toggle="true"> + </button> + <text + follows="left|top" + height="20" + layout="topleft" + left_pad="3" + top="10" + name="back_lbl" + width="40"> + Back + </text> + <text + follows="left|top" + font="SansSerifLarge" + text_color="White" + height="20" + layout="topleft" + left="20" + top_pad="10" + name="av_nearby_title" + width="205"> + Avatars nearby + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left="20" + top_pad="5" + name="av_nearby_desc" + width="580"> + Hide the most complex avatars to boost speed. + </text> + <slider + control_name="RenderAvatarMaxART" + tool_tip="Controls when a visually complex avatar is considered to be taking too long to render (unit: microseconds)" + follows="left|top" + height="16" + initial_value="4.7" + increment="0.01" + label="Maximum render time (μs)" + text_color="White" + label_width="165" + layout="topleft" + min_val="2" + max_val="4.7" + name="RenderAvatarMaxART" + show_text="false" + top_pad="10" + width="490"> + </slider> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + top_delta="0" + left_pad="5" + text_color="White" + name="RenderAvatarMaxARTText" + width="65"> + no limit + </text> + <name_list + column_padding="0" + draw_stripes="true" + height="280" + left="20" + follows="left|top" + layout="topleft" + sort_column="complex_value" + short_names="true" + name="nearby_list" + name_column="name" + top_pad="10" + width="540"> + <name_list.columns + label="" + name="complex_visual" + width="90" /> + <name_list.columns + label="" + name="complex_value" + width="50" /> + <name_list.columns + label="" + name="name"/> + </name_list> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left="20" + top_pad="10" + name="av_nearby_desc2" + width="580"> + You can also right-click on an avatar in-world to control display. + </text> + <button + height="23" + label="Exceptions..." + layout="topleft" + left="460" + top_delta="2" + name="exceptions_btn" + width="100"> + </button> + <check_box + control_name="AlwaysRenderFriends" + height="16" + initial_value="true" + label="Always display friends in full detail" + label_text.text_color="White" + layout="topleft" + name="display_friends" + top_pad="3" + left="18" + width="256"> + </check_box> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border" + top_pad="15" + left="20" + width="540"/> + <check_box + height="16" + initial_value="true" + label="Hide avatars completely (good for landscape photos)" + layout="topleft" + name="hide_avatars" + top_delta="15" + left="18" + width="280"> + </check_box> + <text + type="string" + length="1" + follows="left|top" + height="15" + layout="topleft" + left="20" + name="name_tags_textbox" + top_pad="10" + width="400"> + Name tags: + </text> + <radio_group + control_name="AvatarNameTagMode" + height="20" + layout="topleft" + left="120" + top_delta="0" + name="name_tag_mode"> + <radio_item + label="Off" + name="radio" + top_delta="20" + layout="topleft" + height="16" + left="0" + value="0" + width="75" /> + <radio_item + label="On" + left_pad="0" + layout="topleft" + top_delta="0" + height="16" + name="radio2" + value="1" + width="75" /> + <radio_item + label="Show briefly" + left_pad="0" + name="radio3" + height="16" + layout="topleft" + top_delta="0" + value="2" + width="160" /> + </radio_group> + +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_performance_preferences.xml b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml new file mode 100644 index 0000000000..ee8105eac9 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml @@ -0,0 +1,554 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bevel_style="none" + follows="left|top" + height="580" + width="580" + name="panel_performance_preferences" + layout="topleft" + left="0" + top="0"> + <button + height="16" + width="16" + layout="topleft" + mouse_opaque="true" + follows="left|top" + name="back_btn" + top="7" + image_selected="Arrow_Left_Off" + image_pressed="Arrow_Left_Off" + image_unselected="Arrow_Left_Off" + left="15" + is_toggle="true"> + </button> + <text + follows="left|top" + height="20" + layout="topleft" + left_pad="3" + top="10" + name="back_lbl" + width="40"> + Back + </text> + <text + follows="left|top" + font="SansSerifLarge" + text_color="white" + height="20" + layout="topleft" + left="20" + top_pad="10" + name="settings_title" + width="300"> + Graphics settings + </text> + <button + follows="top|left" + height="23" + label="Open Advanced Settings" + layout="topleft" + left="360" + name="advanced_btn" + top_delta="0" + width="200"/> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border0" + top_pad="8" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="30" + name="quality_lbl" + width="100"> + Quality & Speed + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left_pad="40" + name="fastest_lbl" + width="40"> + Fastest + </text> + <radio_group + control_name="RenderQualityPerformance" + follows="top|left" + draw_border="false" + height="25" + layout="topleft" + left_pad="5" + name="graphics_quality" + top_delta="0" + width="243"> + <radio_item + height="16" + layout="topleft" + left="3" + name="0" + top="0" + width="7" /> + <radio_item + height="16" + layout="topleft" + left_pad="30" + name="1" + width="7" /> + <radio_item + height="16" + layout="topleft" + left_pad="30" + name="2" + width="7" /> + <radio_item + height="16" + layout="topleft" + left_pad="30" + name="3" + width="7" /> + <radio_item + height="16" + layout="topleft" + left_pad="30" + name="4" + width="7" /> + <radio_item + height="16" + layout="topleft" + left_pad="30" + name="5" + width="7" /> + <radio_item + height="16" + layout="topleft" + left_pad="30" + name="6" + width="7" /> + </radio_group> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left_pad="10" + top_delta="1" + name="quality_lbl" + width="70"> + Best quality + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="15" + left="160" + name="quality_desc" + width="380"> + Choosing a shortcut will reset all manual changes you have made. + </text> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border2" + top_pad="5" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="20" + left="20" + name="distance_lbl" + width="100"> + Visibility distance + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left_pad="40" + name="faster_lbl" + width="40"> + Faster + </text> + <slider + control_name="RenderFarClip" + decimal_digits="0" + follows="left|top" + top_delta="-1" + height="16" + increment="8" + initial_value="160" + label_width="90" + layout="topleft" + min_val="64" + max_val="512" + name="draw_distance" + left_pad="5" + width="250"> + </slider> + <text + type="string" + length="1" + follows="left|top" + height="12" + layout="topleft" + left_pad="1" + top_delta="0" + name="draw_distance_m" + width="20"> + m + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + left_pad="10" + top_delta="1" + name="farther_lbl" + width="40"> + Farther + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="15" + left="160" + name="distance_desc1" + width="350"> + To see more land when you zoom out, increase the distance. + </text> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border3" + top_pad="5" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="20" + left="20" + name="environment_lbl" + width="100"> + Environment + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_delta="0" + left="160" + name="enhancements_desc" + width="350"> + Each enhancement improves realism but can reduce speed. + </text> + <check_box + control_name="WindLightUseAtmosShaders" + height="16" + initial_value="true" + label="Atmospheric shaders" + layout="topleft" + name="atmospheric_shaders" + top_pad="5" + left="157" + width="280"> + </check_box> + <check_box + control_name="RenderDeferred" + height="16" + initial_value="true" + label="Advanced Lighting" + layout="topleft" + name="advanced_lighting_model" + top_delta="24" + width="280"> + </check_box> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="160" + name="RenderShadowDetailText" + text_readonly_color="LabelDisabledColor" + top_pad="10" + width="128"> + Shadows: + </text> + <combo_box + control_name="RenderShadowDetail" + height="18" + layout="topleft" + left_delta="150" + top_delta="0" + name="ShadowDetail" + width="150"> + <combo_box.item + label="None" + name="0" + value="0"/> + <combo_box.item + label="Sun/Moon" + name="1" + value="1"/> + <combo_box.item + label="Sun/Moon + Projectors" + name="2" + value="2"/> + </combo_box> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border3" + top_pad="7" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="20" + left="20" + name="water_lbl" + width="100"> + Water + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_delta="0" + left="160" + name="water_desc" + width="380"> + Reducing or turning off water effects can greatly improve frame rate. + </text> + <check_box + control_name="RenderTransparentWater" + height="16" + initial_value="true" + label="Transparent Water" + layout="topleft" + name="TransparentWater" + top_delta="24" + left="157" + width="280"> + </check_box> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + name="ReflectionsText" + text_readonly_color="LabelDisabledColor" + top_pad="16" + left="160" + width="128"> + Water Reflections: + </text> + <combo_box + control_name="RenderReflectionDetail" + height="18" + layout="topleft" + left_delta="150" + top_delta="0" + name="Reflections" + width="150"> + <combo_box.item + label="None; opaque" + name="0" + value="-2"/> + <combo_box.item + label="None; transparent" + name="0" + value="-1"/> + <combo_box.item + label="Minimal" + name="0" + value="0"/> + <combo_box.item + label="Terrain and trees" + name="1" + value="1"/> + <combo_box.item + label="All static objects" + name="2" + value="2"/> + <combo_box.item + label="All avatars and objects" + name="3" + value="3"/> + <combo_box.item + label="Everything" + name="4" + value="4"/> + </combo_box> + <view_border + bevel_style="in" + height="0" + layout="topleft" + name="border4" + top_pad="7" + left="20" + width="540"/> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_pad="20" + left="20" + name="photo_lbl" + width="100"> + Photography + </text> + <text + follows="left|top" + font="SansSerifSmall" + text_color="White" + height="18" + layout="topleft" + top_delta="0" + left="160" + name="photo_desc" + width="350"> + Maximum detail is good for photos, but can slow frame rate. + </text> + <spinner + control_name="RenderVolumeLODFactor" + follows="left|top" + height="23" + increment="0.125" + label="Distance detail:" + label_width="95" + layout="topleft" + max_val="4" + min_val="0" + name="render_volume_lod" + top_pad="10" + width="150" /> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + top_delta="3" + left_pad="10" + name="photo_desc" + width="180"> + (Enter value between 0.0 and 4.0) + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + top="80" + left="213" + name="1_lbl" + width="7"> + 1 + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + left_pad="31" + name="2_lbl" + width="7"> + 2 + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + left_pad="30" + name="3_lbl" + width="7"> + 3 + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + left_pad="30" + name="4_lbl" + width="7"> + 4 + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + left_pad="30" + name="5_lbl" + width="7"> + 5 + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + left_pad="30" + name="6_lbl" + width="7"> + 6 + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="18" + layout="topleft" + left_pad="30" + name="7_lbl" + width="7"> + 7 + </text> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 5aff7a5127..ad02df3087 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -258,6 +258,18 @@ <check_box.commit_callback function="Pref.RenderOptionUpdate" /> </check_box> + + <button + height="23" + label="Automatic adjustments settings" + layout="topleft" + left="30" + name="AutoAdjustmentsButton" + top_delta="30" + width="200"> + <button.commit_callback + function="Pref.AutoAdjustments"/> + </button> <slider control_name="IndirectMaxComplexity" @@ -274,7 +286,7 @@ max_val="101" name="IndirectMaxComplexity" show_text="false" - top_delta="60" + top_delta="40" width="300"> <slider.commit_callback function="Pref.UpdateIndirectMaxComplexity" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 6f95e282ca..22aef0826a 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -4162,6 +4162,7 @@ name="Command_360_Capture_Label">360 snapshot</string> <string name="Command_MiniMap_Label">Mini-map</string> <string name="Command_Move_Label">Walk / run / fly</string> <string name="Command_People_Label">People</string> + <string name="Command_Performance_Label">Graphics speed</string> <string name="Command_Picks_Label">Picks</string> <string name="Command_Places_Label">Places</string> <string name="Command_Preferences_Label">Preferences</string> @@ -4194,6 +4195,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <string name="Command_MiniMap_Tooltip">Show nearby people</string> <string name="Command_Move_Tooltip">Moving your avatar</string> <string name="Command_People_Tooltip">Friends, groups, and nearby people</string> + <string name="Command_Performance_Tooltip">Improve graphics speed</string> <string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string> <string name="Command_Places_Tooltip">Places you've saved</string> <string name="Command_Preferences_Tooltip">Preferences</string> @@ -4292,7 +4294,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <string name="preset_combo_label">-Empty list-</string> <string name="Default">Default</string> <string name="none_paren_cap">(None)</string> - <string name="no_limit">No Limit</string> + <string name="no_limit">No limit</string> <string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES"> The physics shape contains triangles which are too small. Try simplifying the physics model. |