summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt7
-rw-r--r--indra/newview/app_settings/commands.xml10
-rw-r--r--indra/newview/app_settings/settings.xml189
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl50
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskV.glsl75
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl31
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/srgbF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl41
-rw-r--r--indra/newview/app_settings/toolbars.xml1
-rw-r--r--indra/newview/featuretable.txt10
-rw-r--r--indra/newview/featuretable_linux.txt1
-rw-r--r--indra/newview/featuretable_mac.txt12
-rw-r--r--indra/newview/groupchatlistener.cpp10
-rw-r--r--indra/newview/llagent.cpp4
-rw-r--r--indra/newview/llappviewer.cpp165
-rw-r--r--indra/newview/llappviewerwin32.cpp36
-rw-r--r--indra/newview/llavatarrendernotifier.cpp18
-rw-r--r--indra/newview/llavatarrendernotifier.h29
-rw-r--r--indra/newview/lldrawable.cpp6
-rw-r--r--indra/newview/lldrawpool.cpp205
-rw-r--r--indra/newview/lldrawpool.h13
-rw-r--r--indra/newview/lldrawpoolalpha.cpp14
-rw-r--r--indra/newview/lldrawpoolavatar.cpp6
-rw-r--r--indra/newview/lldrawpoolbump.cpp29
-rw-r--r--indra/newview/lldrawpoolbump.h1
-rw-r--r--indra/newview/llfeaturemanager.cpp17
-rw-r--r--indra/newview/llfeaturemanager.h5
-rw-r--r--indra/newview/llfloater360capture.cpp11
-rw-r--r--indra/newview/llfloateravatarrendersettings.cpp38
-rw-r--r--indra/newview/llfloateravatarrendersettings.h4
-rw-r--r--indra/newview/llfloatereditsky.cpp2
-rw-r--r--indra/newview/llfloatereditwater.cpp2
-rw-r--r--indra/newview/llfloaterperformance.cpp748
-rw-r--r--indra/newview/llfloaterperformance.h104
-rw-r--r--indra/newview/llfloaterpreference.cpp395
-rw-r--r--indra/newview/llfloaterpreference.h44
-rw-r--r--indra/newview/llfloaterpreferencesgraphicsadvanced.cpp480
-rw-r--r--indra/newview/llfloaterpreferencesgraphicsadvanced.h68
-rw-r--r--indra/newview/llglsandbox.cpp100
-rw-r--r--indra/newview/llgltfmateriallist.cpp133
-rw-r--r--indra/newview/llgltfmateriallist.h7
-rw-r--r--indra/newview/llmeshrepository.cpp142
-rw-r--r--indra/newview/llmeshrepository.h71
-rw-r--r--indra/newview/llnamelistctrl.cpp69
-rw-r--r--indra/newview/llnamelistctrl.h27
-rw-r--r--indra/newview/llpanelpresetspulldown.cpp12
-rw-r--r--indra/newview/llpanelpresetspulldown.h1
-rw-r--r--indra/newview/llperfstats.cpp566
-rw-r--r--indra/newview/llperfstats.h350
-rw-r--r--indra/newview/llreflectionmap.h8
-rw-r--r--indra/newview/llreflectionmapmanager.cpp315
-rw-r--r--indra/newview/llreflectionmapmanager.h9
-rw-r--r--indra/newview/llselectmgr.cpp36
-rw-r--r--indra/newview/llselectmgr.h3
-rw-r--r--indra/newview/llsettingsvo.cpp32
-rw-r--r--indra/newview/llspatialpartition.cpp115
-rw-r--r--indra/newview/llstartup.cpp8
-rw-r--r--indra/newview/lltoolbarview.cpp20
-rw-r--r--indra/newview/lltooldraganddrop.cpp5
-rw-r--r--indra/newview/llviewercontrol.cpp347
-rw-r--r--indra/newview/llviewerdisplay.cpp9
-rw-r--r--indra/newview/llviewerfloaterreg.cpp3
-rw-r--r--indra/newview/llviewerjointmesh.cpp1
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llviewerobject.cpp14
-rw-r--r--indra/newview/llviewerobject.h9
-rw-r--r--indra/newview/llviewerpartsim.cpp2
-rw-r--r--indra/newview/llviewershadermgr.cpp42
-rw-r--r--indra/newview/llviewershadermgr.h2
-rw-r--r--indra/newview/llviewerstats.cpp103
-rw-r--r--indra/newview/llvoavatar.cpp594
-rw-r--r--indra/newview/llvoavatar.h71
-rw-r--r--indra/newview/llvoavatarself.cpp1
-rw-r--r--indra/newview/llvovolume.cpp322
-rw-r--r--indra/newview/llvovolume.h26
-rw-r--r--indra/newview/llworld.cpp31
-rw-r--r--indra/newview/llworld.h5
-rw-r--r--indra/newview/pipeline.cpp388
-rw-r--r--indra/newview/pipeline.h19
-rw-r--r--indra/newview/skins/default/colors.xml11
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/textures/toolbar_icons/performance.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/default/xui/en/floater_add_payment_method.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_adjust_environment.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_render_settings.xml66
-rw-r--r--indra/newview/skins/default/xui/en/floater_performance.xml368
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_scene_load_stats.xml53
-rw-r--r--indra/newview/skins/default/xui/en/menu_attachment_other.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_other.xml64
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_rendering_settings.xml25
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_rendering_settings_add.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml44
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml49
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml387
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_complexity.xml106
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_huds.xml95
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_nearby.xml216
-rw-r--r--indra/newview/skins/default/xui/en/panel_performance_preferences.xml494
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml14
-rw-r--r--indra/newview/skins/default/xui/en/panel_presets_pulldown.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
105 files changed, 7125 insertions, 1846 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3bc636bac4..c6d82ea260 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -257,10 +257,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
@@ -904,10 +906,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
@@ -1350,6 +1354,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 998d139bf1..df36c51f55 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1426,7 +1426,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <integer>1024</integer>
+ <integer>4096</integer>
</map>
<key>CacheValidateCounter</key>
<map>
@@ -8828,6 +8828,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderClass1MemoryBandwidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Memory bandwidth at which to default to Class 1 in gigabytes per second. Used as basis for higher classes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>32.0</real>
+ </map>
<key>RenderCloudShadowAmbianceFactor</key>
<map>
<key>Comment</key>
@@ -8839,6 +8850,17 @@
<key>Value</key>
<real>0.1</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>
@@ -9061,6 +9083,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>
@@ -9252,6 +9285,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderDisablePostProcessing</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable tone mapping and exposure correction when build floater is open (for artists developing materials)</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderMaxOpenGLVersion</key>
<map>
<key>Comment</key>
@@ -16887,6 +16931,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>15</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>1</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>0</integer>
+ </map>
+ <key>KeepAutoTuneLock</key>
+ <map>
+ <key>Comment</key>
+ <string>When enabled the AutoTuneLock will be maintainted all following sessions.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</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>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, 2=Tune only global scene.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>CameraOpacity</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl
new file mode 100644
index 0000000000..5ef9bb6805
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl
@@ -0,0 +1,50 @@
+/**
+ * @file pbrShadowAlphaMaskF.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+in vec4 post_pos;
+in float target_pos_x;
+in vec4 vertex_color;
+in vec2 vary_texcoord0;
+uniform float minimum_alpha;
+
+void main()
+{
+ float alpha = diffuseLookup(vary_texcoord0.xy).a;
+
+ if (alpha < minimum_alpha)
+ {
+ discard;
+ }
+
+ frag_color = vec4(1,1,1,1);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskV.glsl
new file mode 100644
index 0000000000..4fb5fbcf06
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskV.glsl
@@ -0,0 +1,75 @@
+/**
+ * @file pbrShadowAlphaMaskV.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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$
+ */
+
+uniform mat4 texture_matrix0;
+#if defined(HAS_SKIN)
+uniform mat4 modelview_matrix;
+uniform mat4 projection_matrix;
+mat4 getObjectSkinnedTransform();
+#else
+uniform mat4 modelview_projection_matrix;
+#endif
+
+uniform vec4[2] texture_base_color_transform;
+vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
+
+uniform float shadow_target_width;
+
+in vec3 position;
+in vec4 diffuse_color;
+in vec2 texcoord0;
+
+out vec4 post_pos;
+out float target_pos_x;
+out vec4 vertex_color;
+out vec2 vary_texcoord0;
+
+void passTextureIndex();
+
+void main()
+{
+ //transform vertex
+#if defined(HAS_SKIN)
+ vec4 pre_pos = vec4(position.xyz, 1.0);
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * pre_pos;
+ pos = projection_matrix * pos;
+#else
+ vec4 pre_pos = vec4(position.xyz, 1.0);
+ vec4 pos = modelview_projection_matrix * pre_pos;
+#endif
+
+ target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+ post_pos = pos;
+
+ gl_Position = pos;
+
+ passTextureIndex();
+
+ vary_texcoord0 = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
+ vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index 82d7bb9835..80816912da 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -104,20 +104,20 @@ vec3 toneMapACES_Hill(vec3 color)
uniform float exposure;
uniform float gamma;
-vec3 legacy_adjust_post(vec3 c);
-
-vec3 toneMap(vec3 color, float gs)
+vec3 toneMap(vec3 color)
{
+#ifndef NO_POST
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
- color *= exposure * exp_scale * gs;
+ color *= exposure * exp_scale;
color = toneMapACES_Hill(color);
+#else
+ color *= 0.6;
+#endif
color = linear_to_srgb(color);
- color = legacy_adjust_post(color);
-
return color;
}
@@ -170,22 +170,19 @@ vec3 legacyGamma(vec3 color)
return color;
}
-float legacyGammaApprox()
-{
- //TODO -- figure out how to plumb this in as a uniform
- float c = 0.5;
- float gc = 1.0-pow(c, gamma);
-
- return gc/c * gamma;
-}
-
void main()
{
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
vec4 diff = texture2D(diffuseRect, vary_fragcoord);
- diff.rgb = toneMap(diff.rgb, legacyGammaApprox());
-
+ diff.rgb = toneMap(diff.rgb);
+
+#ifdef LEGACY_GAMMA
+#ifndef NO_POST
+ diff.rgb = legacyGamma(diff.rgb);
+#endif
+#endif
+
vec2 tc = vary_fragcoord.xy*screen_res*4.0;
vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
index eb2ba68415..8c9b6f8190 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
@@ -48,8 +48,6 @@ void main()
discard;
}
-#if !defined(GLTF)
-
#if !defined(IS_FULLBRIGHT)
alpha *= vertex_color.a;
#endif
@@ -66,7 +64,6 @@ void main()
discard;
}
}
-#endif
frag_color = vec4(1,1,1,1);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
index 72a07fa3d0..26db1a5d4d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
@@ -32,9 +32,6 @@ mat4 getObjectSkinnedTransform();
uniform mat4 modelview_projection_matrix;
#endif
-uniform vec4[2] texture_base_color_transform;
-vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
-
uniform float shadow_target_width;
in vec3 position;
@@ -70,6 +67,6 @@ void main()
passTextureIndex();
- vary_texcoord0 = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
vertex_color = diffuse_color;
}
diff --git a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl
index 35f2395ef1..3817633df0 100644
--- a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl
@@ -128,8 +128,3 @@ vec3 legacy_adjust_fullbright(vec3 c)
return c / exp_scale * 1.34;
}
-
-vec3 legacy_adjust_post(vec3 c)
-{
- return c;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 35563713f5..53e15bd1a1 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -47,7 +47,11 @@ layout (std140) uniform ReflectionProbes
mat4 refBox[MAX_REFMAP_COUNT];
// list of bounding spheres for reflection probes sorted by distance to camera (closest first)
vec4 refSphere[MAX_REFMAP_COUNT];
- // extra parameters (currently only .x used for probe ambiance)
+ // extra parameters
+ // x - irradiance scale
+ // y - radiance scale
+ // z - fade in
+ // w - znear
vec4 refParams[MAX_REFMAP_COUNT];
// index of cube map in reflectionProbes for a corresponding reflection probe
// e.g. cube map channel of refSphere[2] is stored in refIndex[2]
@@ -60,6 +64,8 @@ layout (std140) uniform ReflectionProbes
// neighbor list data (refSphere indices, not cubemap array layer)
ivec4 refNeighbor[1024];
+ ivec4 refBucket[256];
+
// number of reflection probes present in refSphere
int refmapCount;
};
@@ -118,13 +124,26 @@ bool shouldSampleProbe(int i, vec3 pos)
return true;
}
+int getStartIndex(vec3 pos)
+{
+#if 1
+ int idx = clamp(int(floor(-pos.z)), 0, 255);
+ return clamp(refBucket[idx].x, 1, refmapCount+1);
+#else
+ return 1;
+#endif
+}
+
// call before sampleRef
// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT
void preProbeSample(vec3 pos)
{
#if REFMAP_LEVEL > 0
+
+ int start = getStartIndex(pos);
+
// TODO: make some sort of structure that reduces the number of distance checks
- for (int i = 1; i < refmapCount; ++i)
+ for (int i = start; i < refmapCount; ++i)
{
// found an influencing probe
if (shouldSampleProbe(i, pos))
@@ -142,6 +161,7 @@ void preProbeSample(vec3 pos)
{
// check up to REF_SAMPLE_COUNT-1 neighbors (neighborIdx is ivec4 index)
+ // sample refNeighbor[neighborIdx].x
int idx = refNeighbor[neighborIdx].x;
if (shouldSampleProbe(idx, pos))
{
@@ -157,6 +177,7 @@ void preProbeSample(vec3 pos)
break;
}
+ // sample refNeighbor[neighborIdx].y
idx = refNeighbor[neighborIdx].y;
if (shouldSampleProbe(idx, pos))
{
@@ -172,6 +193,7 @@ void preProbeSample(vec3 pos)
break;
}
+ // sample refNeighbor[neighborIdx].z
idx = refNeighbor[neighborIdx].z;
if (shouldSampleProbe(idx, pos))
{
@@ -187,6 +209,7 @@ void preProbeSample(vec3 pos)
break;
}
+ // sample refNeighbor[neighborIdx].w
idx = refNeighbor[neighborIdx].w;
if (shouldSampleProbe(idx, pos))
{
@@ -197,11 +220,7 @@ void preProbeSample(vec3 pos)
}
}
count++;
- if (count == neighborCount)
- {
- break;
- }
-
+
++neighborIdx;
}
@@ -735,6 +754,14 @@ vec4 sampleReflectionProbesDebug(vec3 pos)
debugTapRefMap(pos, dir, d, i, col);
}
+#if 0 //debug getStartIndex
+ col.g = float(getStartIndex(pos));
+
+ col.g /= 255.0;
+ col.rb = vec2(0);
+ col.a = 1.0;
+#endif
+
return col;
}
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 78c2578cec..79d92adcc2 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -113,9 +113,9 @@ RenderReflectionProbeLevel 1 0
list LowMid
RenderAnisotropic 1 0
RenderAvatarLODFactor 1 0.5
-RenderAvatarMaxNonImpostors 1 5
RenderAvatarMaxComplexity 1 100000
RenderAvatarPhysicsLODFactor 1 0.75
+RenderAvatarMaxNonImpostors 1 5
RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
@@ -143,9 +143,9 @@ RenderReflectionProbeLevel 1 1
list Mid
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 7
RenderAvatarMaxComplexity 1 200000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 7
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
@@ -173,9 +173,9 @@ RenderReflectionProbeLevel 1 2
list MidHigh
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 9
RenderAvatarMaxComplexity 1 250000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 9
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
@@ -203,9 +203,9 @@ RenderReflectionProbeLevel 1 2
list High
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 11
RenderAvatarMaxComplexity 1 300000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 11
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
@@ -233,9 +233,9 @@ RenderReflectionProbeLevel 1 3
list HighUltra
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 350000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 16
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 66197e6484..4bcefc1546 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -59,7 +59,6 @@ WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
-RenderTextureMemoryMultiple 1 1.0
RenderCompressTextures 1 1
RenderShaderLightingMaxLevel 1 3
RenderDeferred 1 1
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 1d407b52d8..72deabd9f1 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -93,7 +93,7 @@ RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
-RenderVolumeLODFactor 1 0.5
+RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -111,9 +111,9 @@ RenderReflectionProbeLevel 1 0
list LowMid
RenderAnisotropic 1 0
RenderAvatarLODFactor 1 0.5
-RenderAvatarMaxNonImpostors 1 5
RenderAvatarMaxComplexity 1 100000
RenderAvatarPhysicsLODFactor 1 0.75
+RenderAvatarMaxNonImpostors 1 5
RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
@@ -141,9 +141,9 @@ RenderReflectionProbeLevel 1 1
list Mid
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 7
RenderAvatarMaxComplexity 1 200000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 7
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
@@ -171,9 +171,9 @@ RenderReflectionProbeLevel 1 2
list MidHigh
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 9
RenderAvatarMaxComplexity 1 250000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 9
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
@@ -201,9 +201,9 @@ RenderReflectionProbeLevel 1 2
list High
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 11
RenderAvatarMaxComplexity 1 300000
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 11
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
@@ -261,8 +261,8 @@ RenderReflectionProbeLevel 1 3
list Ultra
RenderAnisotropic 1 1
RenderAvatarLODFactor 1 1.0
-RenderAvatarMaxNonImpostors 1 16
RenderAvatarPhysicsLODFactor 1 1.0
+RenderAvatarMaxNonImpostors 1 16
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
diff --git a/indra/newview/groupchatlistener.cpp b/indra/newview/groupchatlistener.cpp
index ef015a950d..a05caa961b 100644
--- a/indra/newview/groupchatlistener.cpp
+++ b/indra/newview/groupchatlistener.cpp
@@ -64,11 +64,11 @@ GroupChatListener::GroupChatListener():
"Leave a group chat in group with UUID [\"id\"]\n"
"Assumes a prior successful startIM request.",
&LLGroupActions::endIM,
- LLSDArray("id"));
- add("sendIM",
- "send a groupchat IM",
- &send_message_wrapper,
- LLSDArray("text")("session_id")("group_id"));
+ llsd::array("id"));
+ add("sendIM",
+ "send a groupchat IM",
+ &send_message_wrapper,
+ llsd::array("text", "session_id", "group_id"));
}
/*
static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id,
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index a68dba98bb..4c3891f302 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -63,6 +63,7 @@
#include "llnotificationsutil.h"
#include "llpaneltopinfobar.h"
#include "llparcel.h"
+#include "llperfstats.h"
#include "llrendersphere.h"
#include "llscriptruntimeperms.h"
#include "llsdutil.h"
@@ -4094,6 +4095,7 @@ void LLAgent::handleTeleportFinished()
mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport));
}
}
+ LLPerfStats::tunables.autoTuneTimeout = true;
}
void LLAgent::handleTeleportFailed()
@@ -4125,6 +4127,8 @@ void LLAgent::handleTeleportFailed()
}
mTPNeedsNeabyChatSeparator = false;
+
+ LLPerfStats::tunables.autoTuneTimeout = true;
}
/*static*/
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b17c78abac..c9fc0e2cc8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -107,6 +107,7 @@
#include "llscenemonitor.h"
#include "llavatarrenderinfoaccountant.h"
#include "lllocalbitmaps.h"
+#include "llperfstats.h"
#include "llgltfmateriallist.h"
// Linden library includes
@@ -1358,82 +1359,93 @@ 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_PROFILE_ZONE_NAMED_CATEGORY_APP("System Messages");
- gViewerWindow->getWindow()->processMiscNativeEvents();
- }
+ if (gViewerWindow)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("System 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_PROFILE_ZONE_NAMED_CATEGORY_APP("System Messages");
- if (!restoreErrorTrap())
- {
- LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
- }
+ if (gViewerWindow)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("System 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 one of our coroutines threw an uncaught exception, rethrow it now
+ LLCoros::instance().rethrow();
+ }
+ }
if (!LLApp::isExiting())
{
@@ -1451,6 +1463,7 @@ bool LLAppViewer::doFrame()
&& (gHeadlessClient || !gViewerWindow->getShowProgress())
&& !gFocusMgr.focusLocked())
{
+ LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE);
joystick->scanJoystick();
gKeyboard->scanKeyboard();
gViewerInput.scanMouse();
@@ -1464,7 +1477,8 @@ bool LLAppViewer::doFrame()
}
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle");
+ LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE);
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle");
idle();
}
@@ -1499,6 +1513,7 @@ bool LLAppViewer::doFrame()
display();
{
+ LLPerfStats::RecordSceneTime T(LLPerfStats::StatType_t::RENDER_IDLE);
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot");
pingMainloopTimeout("Main:Snapshot");
gPipeline.mReflectionMapManager.update();
@@ -1550,7 +1565,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();
}
@@ -1637,7 +1653,7 @@ bool LLAppViewer::doFrame()
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
-
+ }LLPerfStats::StatsRecorder::endFrame();
LL_PROFILER_FRAME_END
return ! LLApp::isRunning();
@@ -2996,15 +3012,9 @@ void LLAppViewer::initStrings()
}
}
-//
-// This function decides whether the client machine meets the minimum requirements to
-// run in a maximized window, per the consensus of davep, boa and nyx on 3/30/2011.
-//
bool LLAppViewer::meetsRequirementsForMaximizedStart()
{
- bool maximizedOk = (LLFeatureManager::getInstance()->getGPUClass() >= GPU_CLASS_2);
-
- maximizedOk &= (gSysMemory.getPhysicalMemoryKB() >= U32Gigabytes(1));
+ bool maximizedOk = (gSysMemory.getPhysicalMemoryKB() >= U32Gigabytes(1));
return maximizedOk;
}
@@ -3181,15 +3191,16 @@ LLSD LLAppViewer::getViewerInfo() const
// LLFloaterAbout.
LLSD info;
auto& versionInfo(LLVersionInfo::instance());
- info["VIEWER_VERSION"] = LLSDArray(versionInfo.getMajor())(versionInfo.getMinor())(versionInfo.getPatch())(versionInfo.getBuild());
+ info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(),
+ versionInfo.getPatch(), versionInfo.getBuild());
info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
info["CHANNEL"] = versionInfo.getChannel();
- info["ADDRESS_SIZE"] = ADDRESS_SIZE;
- std::string build_config = versionInfo.getBuildConfig();
- if (build_config != "Release")
- {
- info["BUILD_CONFIG"] = build_config;
- }
+ info["ADDRESS_SIZE"] = ADDRESS_SIZE;
+ std::string build_config = versionInfo.getBuildConfig();
+ if (build_config != "Release")
+ {
+ info["BUILD_CONFIG"] = build_config;
+ }
// return a URL to the release notes for this viewer, such as:
// https://releasenotes.secondlife.com/viewer/2.1.0.123456.html
@@ -4687,6 +4698,8 @@ void LLAppViewer::idle()
LLFrameTimer::updateFrameTime();
LLFrameTimer::updateFrameCount();
LLEventTimer::updateClass();
+ LLPerfStats::updateClass();
+
// LLApp::stepFrame() performs the above three calls plus mRunner.run().
// Not sure why we don't call stepFrame() here, except that LLRunner seems
// completely redundant with LLEventTimer.
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 6457c13ef3..31c5d2a16f 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -656,16 +656,18 @@ bool LLAppViewerWin32::init()
LL_VIEWER_VERSION_PATCH << '.' <<
LL_VIEWER_VERSION_BUILD));
- DWORD dwFlags = MDSF_NONINTERACTIVE | // automatically submit report without prompting
- MDSF_PREVENTHIJACKING; // disallow swiping Exception filter
-
- bool needs_log_file = !isSecondInstance() && debugLoggingEnabled("BUGSPLAT");
- if (needs_log_file)
- {
- // Startup only!
- LL_INFOS("BUGSPLAT") << "Engaged BugSplat logging to bugsplat.log" << LL_ENDL;
- dwFlags |= MDSF_LOGFILE | MDSF_LOG_VERBOSE;
- }
+ DWORD dwFlags = MDSF_NONINTERACTIVE | // automatically submit report without prompting
+ MDSF_PREVENTHIJACKING; // disallow swiping Exception filter
+
+ bool needs_log_file = !isSecondInstance();
+ LL_DEBUGS("BUGSPLAT");
+ if (needs_log_file)
+ {
+ // Startup only!
+ LL_INFOS("BUGSPLAT") << "Engaged BugSplat logging to bugsplat.log" << LL_ENDL;
+ dwFlags |= MDSF_LOGFILE | MDSF_LOG_VERBOSE;
+ }
+ LL_ENDL;
// have to convert normal wide strings to strings of __wchar_t
sBugSplatSender = new MiniDmpSender(
@@ -676,12 +678,14 @@ bool LLAppViewerWin32::init()
dwFlags);
sBugSplatSender->setCallback(bugsplatSendLog);
- if (needs_log_file)
- {
- // Log file will be created in %TEMP%, but it will be moved into logs folder in case of crash
- std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
- sBugSplatSender->setLogFilePath(WCSTR(log_file));
- }
+ LL_DEBUGS("BUGSPLAT");
+ if (needs_log_file)
+ {
+ // Log file will be created in %TEMP%, but it will be moved into logs folder in case of crash
+ std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
+ sBugSplatSender->setLogFilePath(WCSTR(log_file));
+ }
+ LL_ENDL;
// engage stringize() overload that converts from wstring
LL_INFOS("BUGSPLAT") << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
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/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 04b6ebd14c..ea59a413fa 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -908,12 +908,6 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
LLVector3 cam_pos_from_agent = LLViewerCamera::getInstance()->getOrigin();
LLVector3 cam_to_box_offset = point_to_box_offset(cam_pos_from_agent, av_box);
mDistanceWRTCamera = llmax(0.01f, ll_round(cam_to_box_offset.magVec(), 0.01f));
- LL_DEBUGS("DynamicBox") << volume->getAvatar()->getFullname()
- << " pos (ignored) " << pos
- << " cam pos " << cam_pos_from_agent
- << " box " << av_box[0] << "," << av_box[1]
- << " -> dist " << mDistanceWRTCamera
- << LL_ENDL;
mVObjp->updateLOD();
return;
}
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 3de0e8a7c4..187e290066 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -53,7 +53,6 @@
#include "llvoavatar.h"
#include "llviewershadermgr.h"
-
S32 LLDrawPool::sNumDrawPools = 0;
//=============================
@@ -385,13 +384,13 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, bool texture)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
-
+
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo *pparams = *k;
if (pparams)
{
- pushBatch(*pparams, texture);
+ pushBatch(*pparams, texture);
}
}
}
@@ -420,91 +419,7 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, bool textu
}
}
-void setup_texture_matrix(LLDrawInfo& params)
-{
- if (params.mTextureMatrix)
- { //special case implementation of texture animation here because of special handling of textures for PBR batches
- gGL.getTexUnit(0)->activate();
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.loadMatrix((GLfloat*)params.mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
- }
-}
-
-void teardown_texture_matrix(LLDrawInfo& params)
-{
- if (params.mTextureMatrix)
- {
- gGL.matrixMode(LLRender::MM_TEXTURE0);
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- }
-}
-
-void LLRenderPass::pushGLTFBatches(U32 type)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- auto* begin = gPipeline.beginRenderMap(type);
- auto* end = gPipeline.endRenderMap(type);
- for (LLCullResult::drawinfo_iterator i = begin; i != end; )
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushGLTFBatch");
- LLDrawInfo& params = **i;
- LLCullResult::increment_iterator(i, end);
-
- pushGLTFBatch(params);
- }
-}
-
-void LLRenderPass::pushGLTFBatch(LLDrawInfo& params)
-{
- auto& mat = params.mGLTFMaterial;
-
- mat->bind(params.mTexture);
-
- LLGLDisable cull_face(mat->mDoubleSided ? GL_CULL_FACE : 0);
-
- setup_texture_matrix(params);
-
- applyModelMatrix(params);
-
- params.mVertexBuffer->setBuffer();
- params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
-
- teardown_texture_matrix(params);
-}
-
-void LLRenderPass::pushRiggedGLTFBatches(U32 type)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- LLVOAvatar* lastAvatar = nullptr;
- U64 lastMeshId = 0;
-
- auto* begin = gPipeline.beginRenderMap(type);
- auto* end = gPipeline.endRenderMap(type);
- for (LLCullResult::drawinfo_iterator i = begin; i != end; )
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushRiggedGLTFBatch");
- LLDrawInfo& params = **i;
- LLCullResult::increment_iterator(i, end);
-
- pushRiggedGLTFBatch(params, lastAvatar, lastMeshId);
- }
-}
-
-void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId)
-{
- if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash))
- {
- uploadMatrixPalette(params);
- lastAvatar = params.mAvatar;
- lastMeshId = params.mSkinInfo->mHash;
- }
-
- pushGLTFBatch(params);
-}
-
-void LLRenderPass::pushBatches(U32 type, bool texture, bool batch_textures, bool reset_gltf)
+void LLRenderPass::pushBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
auto* begin = gPipeline.beginRenderMap(type);
@@ -514,12 +429,11 @@ void LLRenderPass::pushBatches(U32 type, bool texture, bool batch_textures, bool
LLDrawInfo* pparams = *i;
LLCullResult::increment_iterator(i, end);
- pushBatch(*pparams, texture, batch_textures, reset_gltf);
- reset_gltf = false;
+ pushBatch(*pparams, texture, batch_textures);
}
}
-void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures, bool reset_gltf)
+void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLVOAvatar* lastAvatar = nullptr;
@@ -538,12 +452,11 @@ void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures
lastMeshId = pparams->mSkinInfo->mHash;
}
- pushBatch(*pparams, texture, batch_textures, reset_gltf);
- reset_gltf = false;
+ pushBatch(*pparams, texture, batch_textures);
}
}
-void LLRenderPass::pushMaskBatches(U32 type, bool texture, bool batch_textures, bool reset_gltf)
+void LLRenderPass::pushMaskBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
auto* begin = gPipeline.beginRenderMap(type);
@@ -553,12 +466,11 @@ void LLRenderPass::pushMaskBatches(U32 type, bool texture, bool batch_textures,
LLDrawInfo* pparams = *i;
LLCullResult::increment_iterator(i, end);
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
- pushBatch(*pparams, texture, batch_textures, reset_gltf);
- reset_gltf = false;
+ pushBatch(*pparams, texture, batch_textures);
}
}
-void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_textures, bool reset_gltf)
+void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLVOAvatar* lastAvatar = nullptr;
@@ -571,6 +483,8 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text
LLCullResult::increment_iterator(i, end);
+ llassert(pparams);
+
if (LLGLSLShader::sCurBoundShaderPtr)
{
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
@@ -587,8 +501,7 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text
lastMeshId = pparams->mSkinInfo->mHash;
}
- pushBatch(*pparams, texture, batch_textures, reset_gltf);
- reset_gltf = false;
+ pushBatch(*pparams, texture, batch_textures);
}
}
@@ -607,14 +520,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
}
}
-void LLRenderPass::resetGLTFTextureTransform()
-{
- F32 ignore_gltf_transform[8];
- LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(ignore_gltf_transform);
- LLGLSLShader::sCurBoundShaderPtr->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)ignore_gltf_transform);
-}
-
-void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textures, bool reset_gltf)
+void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
if (!params.mCount)
@@ -623,7 +529,6 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textur
}
applyModelMatrix(params);
- if (reset_gltf) { resetGLTFTextureTransform(); }
bool tex_setup = false;
@@ -702,3 +607,87 @@ bool LLRenderPass::uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinI
return true;
}
+void setup_texture_matrix(LLDrawInfo& params)
+{
+ if (params.mTextureMatrix)
+ { //special case implementation of texture animation here because of special handling of textures for PBR batches
+ gGL.getTexUnit(0)->activate();
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.loadMatrix((GLfloat*)params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
+}
+
+void teardown_texture_matrix(LLDrawInfo& params)
+{
+ if (params.mTextureMatrix)
+ {
+ gGL.matrixMode(LLRender::MM_TEXTURE0);
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ }
+}
+
+void LLRenderPass::pushGLTFBatches(U32 type)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushGLTFBatch");
+ LLDrawInfo& params = **i;
+ LLCullResult::increment_iterator(i, end);
+
+ pushGLTFBatch(params);
+ }
+}
+
+void LLRenderPass::pushGLTFBatch(LLDrawInfo& params)
+{
+ auto& mat = params.mGLTFMaterial;
+
+ mat->bind(params.mTexture);
+
+ LLGLDisable cull_face(mat->mDoubleSided ? GL_CULL_FACE : 0);
+
+ setup_texture_matrix(params);
+
+ applyModelMatrix(params);
+
+ params.mVertexBuffer->setBuffer();
+ params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
+
+ teardown_texture_matrix(params);
+}
+
+void LLRenderPass::pushRiggedGLTFBatches(U32 type)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+
+ auto* begin = gPipeline.beginRenderMap(type);
+ auto* end = gPipeline.endRenderMap(type);
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; )
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushRiggedGLTFBatch");
+ LLDrawInfo& params = **i;
+ LLCullResult::increment_iterator(i, end);
+
+ pushRiggedGLTFBatch(params, lastAvatar, lastMeshId);
+ }
+}
+
+void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId)
+{
+ if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash))
+ {
+ uploadMatrixPalette(params);
+ lastAvatar = params.mAvatar;
+ lastMeshId = params.mSkinInfo->mHash;
+ }
+
+ pushGLTFBatch(params);
+}
+
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 8704f2e340..eef19199b9 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -349,17 +349,18 @@ public:
void resetDrawOrders() { }
static void applyModelMatrix(const LLDrawInfo& params);
+ // Use before a non-GLTF batch if it is interleaved with GLTF batches that share the same shader
static void resetGLTFTextureTransform();
- virtual void pushBatches(U32 type, bool texture = true, bool batch_textures = false, bool reset_gltf = false);
- virtual void pushRiggedBatches(U32 type, bool texture = true, bool batch_textures = false, bool reset_gltf = false);
+ void pushBatches(U32 type, bool texture = true, bool batch_textures = false);
+ void pushRiggedBatches(U32 type, bool texture = true, bool batch_textures = false);
void pushGLTFBatches(U32 type);
void pushGLTFBatch(LLDrawInfo& params);
void pushRiggedGLTFBatches(U32 type);
void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId);
- virtual void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false, bool reset_gltf = false);
- virtual void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false, bool reset_gltf = false);
- // reset_gltf: batch is interleaved with GLTF batches that share the same shader
- virtual void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false, bool reset_gltf = false);
+ void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false);
+ void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false);
+ void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false);
+ void pushBumpBatch(LLDrawInfo& params, bool texture, bool batch_textures = false);
static bool uploadMatrixPalette(LLDrawInfo& params);
static bool uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo);
virtual void renderGroup(LLSpatialGroup* group, U32 type, bool texture = true);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 280be162bc..f8d2a9e942 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -107,12 +107,10 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
// i.e. shaders\class1\deferred\alphaF.glsl
if (deferredEnvironment)
{
- gPipeline.bindDeferredShader( *shader );
- }
- else
- {
- shader->bind();
+ shader->mCanBindFast = false;
}
+
+ shader->bind();
shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
if (LLPipeline::sRenderingHUDs)
@@ -159,7 +157,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- if ((!LLPipeline::sRenderTransparentWater || gCubeSnapshot) && getType() == LLDrawPool::POOL_ALPHA_PRE_WATER)
+ if (LLPipeline::isWaterClip() && getType() == LLDrawPool::POOL_ALPHA_PRE_WATER)
{ // don't render alpha objects on the other side of the water plane if water is opaque
return;
}
@@ -537,6 +535,8 @@ void LLDrawPoolAlpha::renderRiggedEmissives(std::vector<LLDrawInfo*>& emissives)
for (LLDrawInfo* draw : emissives)
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("Emissives");
+
bool tex_setup = TexSetup(draw, false);
if (lastAvatar != draw->mAvatar || lastMeshId != draw->mSkinInfo->mHash)
{
@@ -664,7 +664,7 @@ 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)
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
if ((bool)params.mAvatar != rigged)
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 9820202f9b..19b23609a6 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -369,9 +369,11 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
{
return;
}
- LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
+
+ LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor();
- if (impostor || (oa == LLVOAvatar::AOA_INVISIBLE))
+ // no shadows if the shadows are causing this avatar to breach the limit.
+ if (avatarp->isTooSlow() || impostor || (oa == LLVOAvatar::AOA_INVISIBLE))
{
// No shadows for impostored (including jellydolled) or invisible avs.
return;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 35265b6df0..38768a19c8 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -77,6 +77,7 @@ static LLGLSLShader* shader = NULL;
static S32 cube_channel = -1;
static S32 diffuse_channel = -1;
static S32 bump_channel = -1;
+static BOOL shiny = FALSE;
// Enabled after changing LLViewerTexture::mNeedsCreateTexture to an
// LLAtomicBool; this should work just fine, now. HB
@@ -197,7 +198,7 @@ void LLStandardBumpmap::destroyGL()
LLDrawPoolBump::LLDrawPoolBump()
: LLRenderPass(LLDrawPool::POOL_BUMP)
{
- mShiny = FALSE;
+ shiny = FALSE;
}
@@ -346,7 +347,7 @@ void LLDrawPoolBump::beginFullbrightShiny()
diffuse_channel = 0;
}
- mShiny = TRUE;
+ shiny = TRUE;
}
void LLDrawPoolBump::renderFullbrightShiny()
@@ -398,14 +399,14 @@ void LLDrawPoolBump::endFullbrightShiny()
diffuse_channel = -1;
cube_channel = 0;
- mShiny = FALSE;
+ shiny = FALSE;
}
void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, bool texture = true)
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
- for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
@@ -541,7 +542,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
- mShiny = TRUE;
+ shiny = TRUE;
for (int i = 0; i < 2; ++i)
{
bool rigged = i == 1;
@@ -575,11 +576,11 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
avatar = params.mAvatar;
skin = params.mSkinInfo->mHash;
}
- pushBatch(params, true, false);
+ pushBumpBatch(params, true, false);
}
else
{
- pushBatch(params, true, false);
+ pushBumpBatch(params, true, false);
}
}
@@ -589,7 +590,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
gGL.getTexUnit(0)->activate();
}
- mShiny = FALSE;
+ shiny = FALSE;
}
@@ -1213,20 +1214,18 @@ void LLDrawPoolBump::pushBumpBatches(U32 type)
}
}
}
- pushBatch(params, false);
+ pushBumpBatch(params, false);
}
}
}
-void LLDrawPoolBump::pushBatch(LLDrawInfo& params, bool texture, bool batch_textures, bool reset_gltf)
+void LLRenderPass::pushBumpBatch(LLDrawInfo& params, bool texture, bool batch_textures)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
applyModelMatrix(params);
bool tex_setup = false;
- if (reset_gltf) { LLRenderPass::resetGLTFTextureTransform(); }
-
if (batch_textures && params.mTextureList.size() > 1)
{
for (U32 i = 0; i < params.mTextureList.size(); ++i)
@@ -1241,7 +1240,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, bool texture, bool batch_text
{ //not batching textures or batch has only 1 texture -- might need a texture matrix
if (params.mTextureMatrix)
{
- if (mShiny)
+ if (shiny)
{
gGL.getTexUnit(0)->activate();
gGL.matrixMode(LLRender::MM_TEXTURE);
@@ -1260,7 +1259,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, bool texture, bool batch_text
tex_setup = true;
}
- if (mShiny && mShaderLevel > 1 && texture)
+ if (shiny && mShaderLevel > 1 && texture)
{
if (params.mTexture.notNull())
{
@@ -1278,7 +1277,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, bool texture, bool batch_text
if (tex_setup)
{
- if (mShiny)
+ if (shiny)
{
gGL.getTexUnit(0)->activate();
}
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 41c4879ded..b1fe454c72 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -53,7 +53,6 @@ public:
LLDrawPoolBump();
/*virtual*/ void prerender() override;
- void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false, bool reset_gltf = false) override;
void pushBumpBatches(U32 type);
void renderGroup(LLSpatialGroup* group, U32 type, bool texture) override;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 0974ae0742..a2aae91ae1 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -408,6 +408,7 @@ bool LLFeatureManager::loadGPUClass()
{
if (!gSavedSettings.getBOOL("SkipBenchmark"))
{
+ F32 class1_gbps = gSavedSettings.getF32("RenderClass1MemoryBandwidth");
//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, default to Low
#if LL_DARWIN
@@ -434,19 +443,19 @@ bool LLFeatureManager::loadGPUClass()
mGPUClass = GPU_CLASS_0;
#endif
}
- else if (gbps <= 32.0f)
+ else if (gbps <= class1_gbps)
{
mGPUClass = GPU_CLASS_1;
}
- else if (gbps <= 64.0f)
+ else if (gbps <= class1_gbps *2.f)
{
mGPUClass = GPU_CLASS_2;
}
- else if (gbps <= 128.0f)
+ else if (gbps <= class1_gbps*4.f)
{
mGPUClass = GPU_CLASS_3;
}
- else if (gbps <= 256.0f)
+ else if (gbps <= class1_gbps*8.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/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp
index 542a1ea39b..23f86e2361 100644
--- a/indra/newview/llfloater360capture.cpp
+++ b/indra/newview/llfloater360capture.cpp
@@ -319,13 +319,7 @@ const std::string LLFloater360Capture::getHTMLBaseFolder()
// triggered when the 'capture' button in the UI is pressed
void LLFloater360Capture::onCapture360ImagesBtn()
{
- // launch the main capture code in a coroutine so we can
- // yield/suspend at some points to give the main UI
- // thread a look-in occasionally.
- LLCoros::instance().launch("capture360cap", [this]()
- {
- capture360Images();
- });
+ capture360Images();
}
// Gets the full path name for a given JavaScript file in the HTML folder. We
@@ -686,9 +680,6 @@ void LLFloater360Capture::capture360Images()
mCaptureBtn->setEnabled(true);
mSaveLocalBtn->setEnabled(true);
- // allow the UI to update by suspending and waiting for the
- // main render loop to update the UI
- suspendForAFrame();
}
// once the request is made to navigate to the web page containing the code
diff --git a/indra/newview/llfloateravatarrendersettings.cpp b/indra/newview/llfloateravatarrendersettings.cpp
index 8b28f6941e..7d098e6c88 100644
--- a/indra/newview/llfloateravatarrendersettings.cpp
+++ b/indra/newview/llfloateravatarrendersettings.cpp
@@ -89,8 +89,6 @@ BOOL LLFloaterAvatarRenderSettings::postBuild()
LLFloater::postBuild();
mAvatarSettingsList = getChild<LLNameListCtrl>("render_settings_list");
mAvatarSettingsList->setRightMouseDownCallback(boost::bind(&LLFloaterAvatarRenderSettings::onAvatarListRightClick, this, _1, _2, _3));
- mAvatarSettingsList->setAlternateSort();
- getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterAvatarRenderSettings::onFilterEdit, this, _2));
return TRUE;
}
@@ -134,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");
- S32 mute_date = LLRenderMuteList::getInstance()->getVisualMuteDate(iter->first);
- item_params.columns.add().value(createTimestamp(mute_date)).column("timestamp").alt_value(std::to_string(mute_date));
- 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);
@@ -215,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/llfloatereditsky.cpp b/indra/newview/llfloatereditsky.cpp
index 6bdc5ee823..2d5e86869d 100644
--- a/indra/newview/llfloatereditsky.cpp
+++ b/indra/newview/llfloatereditsky.cpp
@@ -523,7 +523,7 @@ void LLFloaterEditSky::refreshSkyPresetsList()
for (LLEnvironment::list_name_id_t::iterator it = list.begin(); it != list.end(); ++it)
{
- mSkyPresetCombo->add((*it).first, LLSDArray((*it).first)((*it).second));
+ mSkyPresetCombo->add((*it).first, llsd::array((*it).first, (*it).second));
}
mSkyPresetCombo->setLabel(getString("combo_label"));
diff --git a/indra/newview/llfloatereditwater.cpp b/indra/newview/llfloatereditwater.cpp
index 6e7b777e70..c44ae7faca 100644
--- a/indra/newview/llfloatereditwater.cpp
+++ b/indra/newview/llfloatereditwater.cpp
@@ -335,7 +335,7 @@ void LLFloaterEditWater::refreshWaterPresetsList()
for (LLEnvironment::list_name_id_t::iterator it = list.begin(); it != list.end(); ++it)
{
- mWaterPresetCombo->add((*it).first, LLSDArray((*it).first)((*it).second));
+ mWaterPresetCombo->add((*it).first, llsd::array((*it).first, (*it).second));
}
mWaterPresetCombo->setLabel(getString("combo_label"));
diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp
new file mode 100644
index 0000000000..19fc3e673e
--- /dev/null
+++ b/indra/newview/llfloaterperformance.cpp
@@ -0,0 +1,748 @@
+/**
+ * @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 "llpresetsmanager.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;
+
+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())
+{
+ 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<LLButton>("defaults_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickDefaults, 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));
+
+ if(!LLPerfStats::tunables.userAutoTuneEnabled)
+ {
+ gSavedSettings.setF32("AutoTuneRenderFarClipTarget", LLPipeline::RenderFarClip);
+ }
+
+ LLStringExplicit fps_limit(llformat("%d", gViewerWindow->getWindow()->getRefreshRate()));
+ mAutoadjustmentsPanel->getChild<LLTextBox>("vsync_desc_limit")->setTextArg("[FPS_LIMIT]", fps_limit);
+ mAutoadjustmentsPanel->getChild<LLTextBox>("display_desc")->setTextArg("[FPS_LIMIT]", fps_limit);
+ mAutoadjustmentsPanel->getChild<LLButton>("defaults_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickDefaults, this));
+
+ mStartAutotuneBtn = mAutoadjustmentsPanel->getChild<LLButton>("start_autotune");
+ mStopAutotuneBtn = mAutoadjustmentsPanel->getChild<LLButton>("stop_autotune");
+ mStartAutotuneBtn->setCommitCallback(boost::bind(&LLFloaterPerformance::startAutotune, this));
+ mStopAutotuneBtn->setCommitCallback(boost::bind(&LLFloaterPerformance::stopAutotune, this));
+
+ gSavedPerAccountSettings.declareBOOL("HadEnabledAutoFPS", FALSE, "User had enabled AutoFPS at least once", LLControlVariable::PERSIST_ALWAYS);
+
+ 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()
+{
+ enableAutotuneWarning();
+
+ if (mUpdateTimer->hasExpired() &&
+ !LLFloaterReg::instanceVisible("save_pref_preset", PRESETS_GRAPHIC)) // give user a chance to save the graphics settings before updating them
+ {
+ 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();
+ }
+
+ mUpdateTimer->setTimerExpirySec(REFRESH_INTERVAL);
+ }
+ updateAutotuneCtrls(LLPerfStats::tunables.userAutoTuneEnabled);
+
+ 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);
+
+ LLVOAvatar* avatar = gAgentAvatarp;
+
+ gPipeline.profileAvatar(avatar, true);
+
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ // get max gpu render time of all attachments
+ F32 max_gpu_time = -1.f;
+
+ for (iter = begin; iter != end; ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && attached_object->isHUDAttachment())
+ {
+ max_gpu_time = llmax(max_gpu_time, attached_object->mGPURenderTime);
+ }
+ }
+ }
+
+
+ for (iter = begin; iter != end; ++iter)
+ {
+ if (!iter->second)
+ {
+ continue;
+ }
+
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && attached_object->isHUDAttachment())
+ {
+ F32 gpu_time = attached_object->mGPURenderTime;
+
+ LLSD item;
+ item["special_id"] = attached_object->getID();
+ item["target"] = LLNameListCtrl::SPECIAL;
+ LLSD& row = item["columns"];
+ row[0]["column"] = "complex_visual";
+ row[0]["type"] = "bar";
+ LLSD& value = row[0]["value"];
+ value["ratio"] = gpu_time / max_gpu_time;
+ 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";
+ // show gpu time in us
+ row[1]["value"] = llformat("%.f", gpu_time * 1000.f);
+ row[1]["font"]["name"] = "SANSSERIF";
+
+ row[2]["column"] = "name";
+ row[2]["type"] = "text";
+ row[2]["value"] = attached_object->getAttachmentItemName();
+ 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);
+
+ LLVOAvatar* avatar = gAgentAvatarp;
+
+ gPipeline.profileAvatar(avatar, true);
+
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ // get max gpu render time of all attachments
+ F32 max_gpu_time = -1.f;
+
+ for (iter = begin; iter != end; ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && !attached_object->isHUDAttachment())
+ {
+ max_gpu_time = llmax(max_gpu_time, attached_object->mGPURenderTime);
+ }
+ }
+ }
+
+ {
+ for (iter = begin; iter != end; ++iter)
+ {
+ if (!iter->second)
+ {
+ continue;
+ }
+
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && !attached_object->isHUDAttachment())
+ {
+ F32 gpu_time = attached_object->mGPURenderTime;
+
+ LLSD item;
+ item["special_id"] = attached_object->getID();
+ item["target"] = LLNameListCtrl::SPECIAL;
+ LLSD& row = item["columns"];
+ row[0]["column"] = "complex_visual";
+ row[0]["type"] = "bar";
+ LLSD& value = row[0]["value"];
+ value["ratio"] = gpu_time / max_gpu_time;
+ 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";
+ // show gpu time in us
+ row[1]["value"] = llformat("%.f", gpu_time * 1000.f);
+ row[1]["font"]["name"] = "SANSSERIF";
+
+ row[2]["column"] = "name";
+ row[2]["type"] = "text";
+ row[2]["value"] = attached_object->getAttachmentItemName();
+ 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()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
+ 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;
+ mNearbyMaxGPUTime = LLWorld::getInstance()->getNearbyAvatarsAndMaxGPUTime(valid_nearby_avs);
+
+ std::vector<LLCharacter*>::iterator char_iter = valid_nearby_avs.begin();
+
+ while (char_iter != valid_nearby_avs.end())
+ {
+ LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*char_iter);
+ if (avatar && (LLVOAvatar::AOA_INVISIBLE != avatar->getOverallAppearance()))
+ {
+ F32 render_av_gpu_ms = avatar->getGPURenderTime();
+
+ auto is_slow = avatar->isTooSlow();
+ 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"] = render_av_gpu_ms / mNearbyMaxGPUTime;
+ 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";
+ // use GPU time in us
+ row[1]["value"] = llformat( "%.f", render_av_gpu_ms * 1000.f);
+ row[1]["font"]["name"] = "SANSSERIF";
+
+ row[3]["column"] = "name";
+ row[3]["type"] = "text";
+ row[3]["value"] = avatar->getFullname();
+ row[3]["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::onClickDefaults()
+{
+ LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences");
+ if (instance)
+ {
+ instance->setRecommendedSettings();
+ }
+}
+
+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&notif, 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 = 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");
+ }
+
+}
+
+void LLFloaterPerformance::startAutotune()
+{
+ LLPerfStats::tunables.userAutoTuneEnabled = true;
+}
+
+void LLFloaterPerformance::stopAutotune()
+{
+ LLPerfStats::tunables.userAutoTuneEnabled = false;
+}
+
+void LLFloaterPerformance::updateAutotuneCtrls(bool autotune_enabled)
+{
+ static LLCachedControl<bool> auto_tune_locked(gSavedSettings, "AutoTuneLock");
+ mStartAutotuneBtn->setEnabled(!autotune_enabled && !auto_tune_locked);
+ mStopAutotuneBtn->setEnabled(autotune_enabled && !auto_tune_locked);
+ getChild<LLCheckBoxCtrl>("AutoTuneContinuous")->setEnabled(!autotune_enabled || (autotune_enabled && auto_tune_locked));
+
+ getChild<LLTextBox>("wip_desc")->setVisible(autotune_enabled && !auto_tune_locked);
+ getChild<LLTextBox>("display_desc")->setVisible(LLPerfStats::tunables.vsyncEnabled);
+}
+
+void LLFloaterPerformance::enableAutotuneWarning()
+{
+ if (!gSavedPerAccountSettings.getBOOL("HadEnabledAutoFPS") && LLPerfStats::tunables.userAutoTuneEnabled)
+ {
+ gSavedPerAccountSettings.setBOOL("HadEnabledAutoFPS", TRUE);
+
+ LLNotificationsUtil::add("EnableAutoFPSWarning", LLSD(), LLSD(),
+ [](const LLSD& notif, const LLSD& resp)
+ {
+ S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+ if (opt == 0)
+ { // offer user to save current graphics settings as a preset
+ LLFloaterReg::showInstance("save_pref_preset", PRESETS_GRAPHIC);
+ }
+ });
+ }
+}
+// EOF
diff --git a/indra/newview/llfloaterperformance.h b/indra/newview/llfloaterperformance.h
new file mode 100644
index 0000000000..620dbac5bb
--- /dev/null
+++ b/indra/newview/llfloaterperformance.h
@@ -0,0 +1,104 @@
+/**
+ * @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 onClickDefaults();
+ void onChangeQuality(const LLSD& data);
+ void onClickHideAvatars();
+ void onClickExceptions();
+ void onClickShadows();
+ void onClickAdvancedLighting();
+
+ void startAutotune();
+ void stopAutotune();
+ void updateAutotuneCtrls(bool autotune_enabled);
+ void enableAutotuneWarning();
+
+ 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;
+
+ LLButton* mStartAutotuneBtn;
+ LLButton* mStopAutotuneBtn;
+
+ LLListContextMenu* mContextMenu;
+
+ LLTimer* mUpdateTimer;
+
+ // maximum GPU time of nearby avatars in ms according to LLWorld::getNearbyAvatarsAndMaxGPUTime
+ // -1.f if no profile has happened yet
+ F32 mNearbyMaxGPUTime = -1.f;
+
+ boost::signals2::connection mMaxARTChangedSignal;
+};
+
+#endif // LL_LLFLOATERPERFORMANCE_H
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 7487c1c9f9..d4e40ff103 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"
@@ -97,11 +98,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"
@@ -114,10 +113,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";
@@ -289,6 +287,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));
@@ -317,9 +316,12 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2));
gSavedSettings.getControl("AppearanceCameraMovement")->getCommitSignal()->connect(boost::bind(&handleAppearanceCameraMovementChanged, _2));
+ gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLFloaterPreference::onAtmosShaderChange, this));
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 +489,7 @@ void LLFloaterPreference::onDoNotDisturbResponseChanged()
LLFloaterPreference::~LLFloaterPreference()
{
LLConversationLog::instance().removeObserver(this);
+ mComplexityChangedSignal.disconnect();
}
void LLFloaterPreference::draw()
@@ -730,13 +733,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();
@@ -752,33 +757,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();
@@ -812,6 +790,13 @@ void LLFloaterPreference::setHardwareDefaults()
saveGraphicsPreset(preset_graphic_active);
saveSettings(); // save here to be able to return to the previous preset by Cancel
}
+ setRecommendedSettings();
+}
+
+void LLFloaterPreference::setRecommendedSettings()
+{
+ resetAutotuneSettings();
+ gSavedSettings.getControl("RenderVSyncEnable")->resetToDefault(true);
LLFeatureManager::getInstance()->applyRecommendedSettings();
@@ -836,6 +821,28 @@ void LLFloaterPreference::setHardwareDefaults()
}
}
+void LLFloaterPreference::resetAutotuneSettings()
+{
+ gSavedSettings.setBOOL("AutoTuneFPS", FALSE);
+
+ const std::string autotune_settings[] = {
+ "AutoTuneLock",
+ "KeepAutoTuneLock",
+ "TargetFPS",
+ "TuningFPSStrategy",
+ "AutoTuneImpostorByDistEnabled",
+ "AutoTuneImpostorFarAwayDistance" ,
+ "AutoTuneRenderFarClipMin",
+ "AutoTuneRenderFarClipTarget",
+ "RenderAvatarMaxART"
+ };
+
+ for (auto it : autotune_settings)
+ {
+ gSavedSettings.getControl(it)->resetToDefault(true);
+ }
+}
+
void LLFloaterPreference::getControlNames(std::vector<std::string>& names)
{
LLView* view = findChild<LLView>("display");
@@ -1194,62 +1201,6 @@ void LLFloaterPreference::refreshEnabledState()
getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess());
}
-void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
-{
- // WindLight
- LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
- LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
- sky->setEnabled(TRUE);
- sky_text->setEnabled(TRUE);
-
- LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
- LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
- LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
- LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText");
-
- BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO");
-
- ctrl_ssao->setEnabled(enabled);
- ctrl_dof->setEnabled(enabled);
-
- enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail");
-
- ctrl_shadow->setEnabled(enabled);
- shadow_text->setEnabled(enabled);
-
- if (!LLFeatureManager::instance().isFeatureAvailable("RenderFSAASamples"))
- {
- getChildView("fsaa")->setEnabled(FALSE);
- }
-
- enabled = false;
- if (!LLFeatureManager::instance().isFeatureAvailable("RenderReflectionsEnabled"))
- {
- getChildView("ReflectionsEnabled")->setEnabled(FALSE);
- }
- else
- {
- enabled = gSavedSettings.getBOOL("RenderReflectionsEnabled");
- }
-
- getChildView("ReflectionDetail")->setEnabled(enabled);
- getChildView("ReflectionDetailText")->setEnabled(enabled);
- getChildView("ScreenSpaceReflections")->setEnabled(enabled);
-
- // Hardware settings
-
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures"))
- {
- getChildView("texture compression")->setEnabled(FALSE);
- }
-
- getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"));
-
- // now turn off any features that are unavailable
- disableUnavailableSettings();
-}
-
-// static
void LLAvatarComplexityControls::setIndirectControls()
{
/*
@@ -1291,63 +1242,6 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
gSavedSettings.setU32("IndirectMaxComplexity", indirect_max_arc);
}
-void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
-{
- 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"))
- {
- 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);
- }
-
- // 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);
- }
-
- // 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);
- }
-}
-
void LLFloaterPreference::refresh()
{
LLPanel::refresh();
@@ -1363,32 +1257,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();
@@ -1600,64 +1468,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
@@ -1679,10 +1490,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)
{
@@ -1690,24 +1501,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)
@@ -1749,22 +1576,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");
@@ -1877,6 +1688,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");
@@ -1899,6 +1719,22 @@ void LLFloaterPreference::onClickActionChange()
updateClickActionControls();
}
+void LLFloaterPreference::onAtmosShaderChange()
+{
+ LLCheckBoxCtrl* ctrl_alm = getChild<LLCheckBoxCtrl>("UseLightShaders");
+ if(ctrl_alm)
+ {
+ //Deferred/SSAO/Shadows
+ BOOL bumpshiny = LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump");
+ BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
+ BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
+ bumpshiny &&
+ shaders;
+
+ ctrl_alm->setEnabled(enabled);
+ }
+}
+
void LLFloaterPreference::onClickPermsDefault()
{
LLFloaterReg::showInstance("perms_default");
@@ -3219,18 +3055,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)
@@ -3240,41 +3064,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 bab1ffdd56..04ac87364d 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -109,10 +109,11 @@ public:
void updateClickActionViews();
void updateSearchableItems();
-protected:
void onBtnOK(const LLSD& userdata);
void onBtnCancel(const LLSD& userdata);
+protected:
+
void onClickClearCache(); // Clear viewer texture cache, file cache on next startup
void onClickBrowserClearCache(); // Clear web history and caches as well as viewer caches above
void onLanguageChange();
@@ -138,6 +139,8 @@ protected:
// updates click/double-click action keybindngs depending on view values
void updateClickActionControls();
+ void onAtmosShaderChange();
+
public:
// This function squirrels away the current values of the controls so that
// cancel() can restore them.
@@ -188,6 +191,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);
@@ -198,12 +202,16 @@ public:
void saveCameraPreset(std::string& preset);
void saveGraphicsPreset(std::string& preset);
+ void setRecommendedSettings();
+ void resetAutotuneSettings();
+
private:
void onDeleteTranscripts();
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;
@@ -225,6 +233,8 @@ private:
std::unique_ptr< ll::prefs::SearchData > mSearchData;
bool mSearchDataDirty;
+ boost::signals2::connection mComplexityChangedSignal;
+
void onUpdateFilterTerm( bool force = false );
void collectSearchableItems();
void filterIgnorableNotifications();
@@ -354,37 +364,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..a91f0ec060
--- /dev/null
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
@@ -0,0 +1,480 @@
+/**
+ * @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();
+ mLODFactorChangedSignal.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));
+ mLODFactorChangedSignal = gSavedSettings.getControl("RenderVolumeLODFactor")->getCommitSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateObjectMeshDetailText, 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::updateObjectMeshDetailText()
+{
+ updateSliderText(getChild<LLSliderCtrl>("ObjectMeshDetail", true), getChild<LLTextBox>("ObjectMeshDetailText", 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 = LLCubeMap::sUseCubeMaps;
+ ctrl_reflections->setEnabled(reflections);
+ reflections_text->setEnabled(reflections);
+
+ // Bump & Shiny
+ LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
+ bool bumpshiny = 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");
+ //ctrl_wind_light->setEnabled(TRUE);
+ LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
+ LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
+ sky->setEnabled(TRUE);
+ sky_text->setEnabled(TRUE);
+
+ BOOL enabled = TRUE;
+#if 0 // deferred always on now
+ //Deferred/SSAO/Shadows
+ LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
+
+ enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
+ ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
+ (ctrl_wind_light->get()) ? TRUE : FALSE;
+
+ ctrl_deferred->setEnabled(enabled);
+#endif
+
+ LLCheckBoxCtrl* ctrl_pbr = getChild<LLCheckBoxCtrl>("UsePBRShaders");
+
+ //PBR
+ ctrl_pbr->setEnabled(TRUE);
+
+ 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
+
+ if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable"))
+ {
+ getChildView("vbo")->setEnabled(FALSE);
+ }
+
+ if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures"))
+ {
+ 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..2c92f3dbf1
--- /dev/null
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.h
@@ -0,0 +1,68 @@
+/**
+ * @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 updateObjectMeshDetailText();
+ 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;
+ boost::signals2::connection mLODFactorChangedSignal;
+};
+
+#endif //LLFLOATERPREFERENCEGRAPHICSADVANCED_H
+
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 2e4d0f85b9..098fe89265 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()
{
@@ -1028,8 +1029,6 @@ F32 gpu_benchmark()
//time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark.
const F32 time_limit = 30;
- ShaderProfileHelper initProfile;
-
std::vector<LLRenderTarget> dest(count);
TextureHolder texHolder(0, count);
std::vector<F32> results;
@@ -1111,46 +1110,49 @@ F32 gpu_benchmark()
buff->unmapBuffer();
- // ensure matched pair of bind() and unbind() calls
- ShaderBinder binder(gBenchmarkProgram);
-
- buff->setBuffer();
- glFinish();
-
- F32 time_passed = 0; // seconds
- for (S32 c = -1; c < samples && time_passed < time_limit; ++c)
- {
- LLTimer timer;
- timer.start();
-
- for (U32 i = 0; i < count; ++i)
- {
- dest[i].bindTarget();
- texHolder.bind(i);
- buff->drawArrays(LLRender::TRIANGLES, 0, 3);
- dest[i].flush();
- }
-
- //wait for current batch of copies to finish
- glFinish();
-
- F32 time = timer.getElapsedTimeF32();
- time_passed += time;
-
- if (c >= 0) // <-- ignore the first sample as it tends to be artificially slow
- {
- //store result in gigabytes per second
- F32 gb = (F32) ((F64) (res*res*8*count))/(1000000000);
- F32 gbps = gb/time;
- results.push_back(gbps);
- }
- }
+ LLGLSLShader::unbind();
+
+ F32 time_passed = 0; // seconds
+
+ { //run CPU timer benchmark
+ glFinish();
+ gBenchmarkProgram.bind();
+ for (S32 c = -1; c < samples && time_passed < time_limit; ++c)
+ {
+ LLTimer timer;
+ timer.start();
+
+ for (U32 i = 0; i < count; ++i)
+ {
+ dest[i].bindTarget();
+ texHolder.bind(i);
+ buff->setBuffer();
+ buff->drawArrays(LLRender::TRIANGLES, 0, 3);
+ dest[i].flush();
+ }
+
+ //wait for current batch of copies to finish
+ glFinish();
+
+ F32 time = timer.getElapsedTimeF32();
+ time_passed += time;
+
+ if (c >= 0) // <-- ignore the first sample as it tends to be artificially slow
+ {
+ //store result in gigabytes per second
+ F32 gb = (F32)((F64)(res * res * 8 * count)) / (1000000000);
+ F32 gbps = gb / time;
+ results.push_back(gbps);
+ }
+ }
+ gBenchmarkProgram.unbind();
+ }
std::sort(results.begin(), results.end());
F32 gbps = results[results.size()/2];
- LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to CPU timers, " << (F32)results.size() << " tests took " << time_passed << " seconds" << LL_ENDL;
+ LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << " GB/sec according to CPU timers, " << (F32)results.size() << " tests took " << time_passed << " seconds" << LL_ENDL;
#if LL_DARWIN
if (gbps > 512.f)
@@ -1161,14 +1163,32 @@ F32 gpu_benchmark()
}
#endif
+ // run GPU timer benchmark
+ {
+ ShaderProfileHelper initProfile;
+ dest[0].bindTarget();
+ gBenchmarkProgram.bind();
+ for (S32 c = 0; c < samples; ++c)
+ {
+ for (U32 i = 0; i < count; ++i)
+ {
+ texHolder.bind(i);
+ buff->setBuffer();
+ buff->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
+ }
+ gBenchmarkProgram.unbind();
+ dest[0].flush();
+ }
+
F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f;
F32 seconds = ms/1000.f;
- F64 samples_drawn = res*res*count*results.size();
+ F64 samples_drawn = gBenchmarkProgram.mSamplesDrawn;
F32 samples_sec = (samples_drawn/1000000000.0)/seconds;
- gbps = samples_sec*8;
+ gbps = samples_sec*4; // 4 bytes per sample
- LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL;
+ LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL;
return gbps;
}
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
index 151d7fa969..99a052f719 100644
--- a/indra/newview/llgltfmateriallist.cpp
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -219,40 +219,36 @@ public:
struct ReturnData
{
public:
- LLPointer<LLGLTFMaterial> mMaterial;
+ LLGLTFMaterial mMaterial;
S32 mSide;
bool mSuccess;
};
- // fromJson() is performance heavy offload to a thread.
- main_queue->postTo(
- general_queue,
- [object_override]() // Work done on general queue
+ if (!object_override.mSides.empty())
{
- std::vector<ReturnData> results;
-
- if (!object_override.mSides.empty())
+ // fromJson() is performance heavy offload to a thread.
+ main_queue->postTo(
+ general_queue,
+ [sides=object_override.mSides]() // Work done on general queue
{
- results.reserve(object_override.mSides.size());
+ std::vector<ReturnData> results;
+
+ results.reserve(sides.size());
// parse json
- std::unordered_map<S32, std::string>::const_iterator iter = object_override.mSides.begin();
- std::unordered_map<S32, std::string>::const_iterator end = object_override.mSides.end();
+ std::unordered_map<S32, std::string>::const_iterator iter = sides.begin();
+ std::unordered_map<S32, std::string>::const_iterator end = sides.end();
while (iter != end)
{
- LLPointer<LLGLTFMaterial> override_data = new LLGLTFMaterial();
std::string warn_msg, error_msg;
- bool success = override_data->fromJSON(iter->second, warn_msg, error_msg);
-
ReturnData result;
+
+ bool success = result.mMaterial.fromJSON(iter->second, warn_msg, error_msg);
+
result.mSuccess = success;
result.mSide = iter->first;
- if (success)
- {
- result.mMaterial = override_data;
- }
- else
+ if (!success)
{
LL_WARNS("GLTF") << "failed to parse GLTF override data. errors: " << error_msg << " | warnings: " << warn_msg << LL_ENDL;
}
@@ -260,64 +256,68 @@ public:
results.push_back(result);
iter++;
}
- }
- return results;
- },
- [object_override, this](std::vector<ReturnData> results) // Callback to main thread
+ return results;
+ },
+ [object_id=object_override.mObjectId, this](std::vector<ReturnData> results) // Callback to main thread
{
- LLViewerObject * obj = gObjectList.findObject(object_override.mObjectId);
+ LLViewerObject * obj = gObjectList.findObject(object_id);
- if (results.size() > 0 )
- {
- std::unordered_set<S32> side_set;
-
- for (int i = 0; i < results.size(); ++i)
+ if (results.size() > 0 )
{
- if (results[i].mSuccess)
+ std::unordered_set<S32> side_set;
+
+ for (auto const & result : results)
{
- // flag this side to not be nulled out later
- side_set.insert(results[i].mSide);
+ S32 side = result.mSide;
+ if (result.mSuccess)
+ {
+ // copy to heap here because LLTextureEntry is going to take ownership with an LLPointer
+ LLGLTFMaterial * material = new LLGLTFMaterial(result.mMaterial);
+
+ // flag this side to not be nulled out later
+ side_set.insert(side);
- if (obj)
+ if (obj)
+ {
+ obj->setTEGLTFMaterialOverride(side, material);
+ }
+ }
+
+ // unblock material editor
+ if (obj && obj->getTE(side) && obj->getTE(side)->isSelected())
{
- obj->setTEGLTFMaterialOverride(results[i].mSide, results[i].mMaterial);
+ doSelectionCallbacks(object_id, side);
}
}
-
- // unblock material editor
- if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected())
- {
- doSelectionCallbacks(object_override.mObjectId, results[i].mSide);
- }
- }
- if (obj && side_set.size() != obj->getNumTEs())
- { // object exists and at least one texture entry needs to have its override data nulled out
- for (int i = 0; i < obj->getNumTEs(); ++i)
- {
- if (side_set.find(i) == side_set.end())
+ if (obj && side_set.size() != obj->getNumTEs())
+ { // object exists and at least one texture entry needs to have its override data nulled out
+ for (int i = 0; i < obj->getNumTEs(); ++i)
{
- obj->setTEGLTFMaterialOverride(i, nullptr);
- if (obj->getTE(i) && obj->getTE(i)->isSelected())
+ if (side_set.find(i) == side_set.end())
{
- doSelectionCallbacks(object_override.mObjectId, i);
+ obj->setTEGLTFMaterialOverride(i, nullptr);
+ if (obj->getTE(i) && obj->getTE(i)->isSelected())
+ {
+ doSelectionCallbacks(object_id, i);
+ }
}
}
}
}
- }
- else if (obj)
- { // override list was empty or an error occurred, null out all overrides for this object
- for (int i = 0; i < obj->getNumTEs(); ++i)
- {
- obj->setTEGLTFMaterialOverride(i, nullptr);
- if (obj->getTE(i) && obj->getTE(i)->isSelected())
+ else if (obj)
+ { // override list was empty or an error occurred, null out all overrides for this object
+ for (int i = 0; i < obj->getNumTEs(); ++i)
{
- doSelectionCallbacks(obj->getID(), i);
+ obj->setTEGLTFMaterialOverride(i, nullptr);
+ if (obj->getTE(i) && obj->getTE(i)->isSelected())
+ {
+ doSelectionCallbacks(obj->getID(), i);
+ }
}
}
- }
- });
+ });
+ }
}
private:
@@ -433,6 +433,19 @@ void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const L
}
}
+void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id, const LLGLTFMaterial* material_override)
+{
+ if (asset_id.isNull() || material_override == nullptr)
+ {
+ queueApply(obj, side, asset_id);
+ }
+ else
+ {
+ LLGLTFMaterial* material = new LLGLTFMaterial(*material_override);
+ sApplyQueue.push_back({ obj->getID(), side, asset_id, material });
+ }
+}
+
void LLGLTFMaterialList::queueUpdate(const LLSD& data)
{
llassert(is_valid_update(data));
@@ -477,7 +490,7 @@ void LLGLTFMaterialList::flushUpdates(void(*done_callback)(bool))
}
sModifyQueue.clear();
- for (auto& e : sApplyQueue)
+ for (ApplyMaterialAssetData& e : sApplyQueue)
{
data[i]["object_id"] = e.object_id;
data[i]["side"] = e.side;
diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h
index 85e60aa17f..ce8781baba 100644
--- a/indra/newview/llgltfmateriallist.h
+++ b/indra/newview/llgltfmateriallist.h
@@ -70,6 +70,13 @@ public:
// NOTE: Implicitly clears most override data if present
static void queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id);
+ // Queue an application of a material asset we want to send to the simulator. Call "flushUpdates" to flush pending updates.
+ // object_id - ID of object to apply material asset to
+ // side - TextureEntry index to apply material to, or -1 for all sides
+ // asset_id - ID of material asset to apply, or LLUUID::null to disassociate current material asset
+ // mat - override material, if null, will clear most override data
+ static void queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id, const LLGLTFMaterial* mat);
+
// flush pending material updates to the simulator
// Automatically called once per frame, but may be called explicitly
// for cases that care about the done_callback forwarded to LLCoros::instance().launch
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index e8411dd573..67bf6827ad 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1342,10 +1342,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
if (header_size > 0)
{
- const LLSD& header = header_it->second.second;
- S32 version = header["version"].asInteger();
- S32 offset = header_size + header["skin"]["offset"].asInteger();
- S32 size = header["skin"]["size"].asInteger();
+ const LLMeshHeader& header = header_it->second.second;
+
+ S32 version = header.mVersion;
+ S32 offset = header_size + header.mSkinOffset;
+ S32 size = header.mSkinSize;
mHeaderMutex->unlock();
@@ -1456,9 +1457,9 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (header_size > 0)
{
const auto& header = header_it->second.second;
- S32 version = header["version"].asInteger();
- S32 offset = header_size + header["physics_convex"]["offset"].asInteger();
- S32 size = header["physics_convex"]["size"].asInteger();
+ S32 version = header.mVersion;
+ S32 offset = header_size + header.mPhysicsConvexOffset;
+ S32 size = header.mPhysicsConvexSize;
mHeaderMutex->unlock();
@@ -1555,9 +1556,9 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (header_size > 0)
{
const auto& header = header_it->second.second;
- S32 version = header["version"].asInteger();
- S32 offset = header_size + header["physics_mesh"]["offset"].asInteger();
- S32 size = header["physics_mesh"]["size"].asInteger();
+ S32 version = header.mVersion;
+ S32 offset = header_size + header.mPhysicsMeshOffset;
+ S32 size = header.mPhysicsMeshSize;
mHeaderMutex->unlock();
@@ -1753,9 +1754,9 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
if (header_size > 0)
{
const auto& header = header_it->second.second;
- S32 version = header["version"].asInteger();
- S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger();
- S32 size = header[header_lod[lod]]["size"].asInteger();
+ S32 version = header.mVersion;
+ S32 offset = header_size + header.mLodOffset[lod];
+ S32 size = header.mLodSize[lod];
mHeaderMutex->unlock();
if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
@@ -1857,8 +1858,10 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size)
{
const LLUUID mesh_id = mesh_params.getSculptID();
- LLSD header;
+ LLSD header_data;
+ LLMeshHeader header;
+
U32 header_size = 0;
if (data_size > 0)
{
@@ -1869,23 +1872,25 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
boost::iostreams::stream<boost::iostreams::array_source> stream(result_ptr, data_size);
- if (!LLSDSerialize::fromBinary(header, stream, data_size))
+ if (!LLSDSerialize::fromBinary(header_data, stream, data_size))
{
LL_WARNS(LOG_MESH) << "Mesh header parse error. Not a valid mesh asset! ID: " << mesh_id
<< LL_ENDL;
return MESH_PARSE_FAILURE;
}
- if (!header.isMap())
+ if (!header_data.isMap())
{
LL_WARNS(LOG_MESH) << "Mesh header is invalid for ID: " << mesh_id << LL_ENDL;
return MESH_INVALID;
}
- if (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION)
+ header.fromLLSD(header_data);
+
+ if (header.mVersion > MAX_MESH_VERSION)
{
LL_INFOS(LOG_MESH) << "Wrong version in header for " << mesh_id << LL_ENDL;
- header["404"] = 1;
+ header.m404 = true;
}
// make sure there is at least one lod, function returns -1 and marks as 404 otherwise
else if (LLMeshRepository::getActualMeshLOD(header, 0) >= 0)
@@ -1897,7 +1902,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
{
LL_INFOS(LOG_MESH) << "Non-positive data size. Marking header as non-existent, will not retry. ID: " << mesh_id
<< LL_ENDL;
- header["404"] = 1;
+ header.m404 = 1;
}
{
@@ -1907,7 +1912,6 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
mMeshHeader[mesh_id] = { header_size, header };
LLMeshRepository::sCacheBytesHeaders += header_size;
}
-
LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.
@@ -2977,7 +2981,7 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
if (iter != mMeshHeader.end())
{
- LLSD& header = iter->second.second;
+ auto& header = iter->second.second;
return LLMeshRepository::getActualMeshLOD(header, lod);
}
@@ -2986,23 +2990,23 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
}
//static
-S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
+S32 LLMeshRepository::getActualMeshLOD(LLMeshHeader& header, S32 lod)
{
lod = llclamp(lod, 0, 3);
- if (header.has("404"))
+ if (header.m404)
{
return -1;
}
- S32 version = header["version"];
+ S32 version = header.mVersion;
if (version > MAX_MESH_VERSION)
{
return -1;
}
- if (header[header_lod[lod]]["size"].asInteger() > 0)
+ if (header.mLodSize[lod] > 0)
{
return lod;
}
@@ -3010,7 +3014,7 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
//search down to find the next available lower lod
for (S32 i = lod-1; i >= 0; --i)
{
- if (header[header_lod[i]]["size"].asInteger() > 0)
+ if (header.mLodSize[i] > 0)
{
return i;
}
@@ -3019,15 +3023,16 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
//search up to find then ext available higher lod
for (S32 i = lod+1; i < 4; ++i)
{
- if (header[header_lod[i]]["size"].asInteger() > 0)
+ if (header.mLodSize[i] > 0)
{
return i;
}
}
//header exists and no good lod found, treat as 404
- header["404"] = 1;
- return -1;
+ header.m404 = true;
+
+ return -1;
}
// Handle failed or successful requests for mesh assets.
@@ -3216,7 +3221,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
{
// header was successfully retrieved from sim and parsed and is in cache
S32 header_bytes = 0;
- LLSD header;
+ LLMeshHeader header;
gMeshRepo.mThread->mHeaderMutex->lock();
LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id);
@@ -3227,8 +3232,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
}
if (header_bytes > 0
- && !header.has("404")
- && (!header.has("version") || header["version"].asInteger() <= MAX_MESH_VERSION))
+ && !header.m404
+ && (header.mVersion <= MAX_MESH_VERSION))
{
std::stringstream str;
@@ -3237,13 +3242,12 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i)
{
// figure out how many bytes we'll need to reserve in the file
- const std::string & lod_name = header_lod[i];
- lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger());
+ lod_bytes = llmax(lod_bytes, header.mLodOffset[i]+header.mLodSize[i]);
}
// just in case skin info or decomposition is at the end of the file (which it shouldn't be)
- lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
- lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
+ lod_bytes = llmax(lod_bytes, header.mSkinOffset+header.mSkinSize);
+ lod_bytes = llmax(lod_bytes, header.mPhysicsConvexOffset + header.mPhysicsConvexSize);
// Do not unlock mutex untill we are done with LLSD.
// LLSD is smart and can work like smart pointer, is not thread safe.
@@ -4257,8 +4261,8 @@ bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id)
mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
if (iter != mMeshHeader.end() && iter->second.first > 0)
{
- LLSD &mesh = iter->second.second;
- if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
+ LLMeshHeader &mesh = iter->second.second;
+ if (mesh.mPhysicsMeshSize > 0)
{
return true;
}
@@ -4281,20 +4285,21 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
if (mThread && mesh_id.notNull() && LLPrimitive::NO_LOD != lod)
{
LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
{
- const LLSD& header = iter->second.second;
+ const LLMeshHeader& header = iter->second.second;
- if (header.has("404"))
+ if (header.m404)
{
return -1;
}
- S32 size = header[header_lod[lod]]["size"].asInteger();
+ S32 size = header.mLodSize[lod];
return size;
}
@@ -4430,11 +4435,11 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* by
// FIXME replace with calc based on LLMeshCostData
//static
-F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
+F32 LLMeshRepository::getStreamingCostLegacy(LLMeshHeader& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
{
- if (header.has("404")
- || !header.has("lowest_lod")
- || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION))
+ if (header.m404
+ || header.mLodSize[0] <= 0
+ || (header.mVersion > MAX_MESH_VERSION))
{
return 0.f;
}
@@ -4453,10 +4458,10 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* byte
F32 minimum_size = (F32)minimum_size_ch;
F32 bytes_per_triangle = (F32)bytes_per_triangle_ch;
- S32 bytes_lowest = header["lowest_lod"]["size"].asInteger();
- S32 bytes_low = header["low_lod"]["size"].asInteger();
- S32 bytes_mid = header["medium_lod"]["size"].asInteger();
- S32 bytes_high = header["high_lod"]["size"].asInteger();
+ S32 bytes_lowest = header.mLodSize[0];
+ S32 bytes_low = header.mLodSize[1];
+ S32 bytes_mid = header.mLodSize[2];
+ S32 bytes_high = header.mLodSize[3];
if (bytes_high == 0)
{
@@ -4486,10 +4491,10 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* byte
if (bytes)
{
*bytes = 0;
- *bytes += header["lowest_lod"]["size"].asInteger();
- *bytes += header["low_lod"]["size"].asInteger();
- *bytes += header["medium_lod"]["size"].asInteger();
- *bytes += header["high_lod"]["size"].asInteger();
+ *bytes += header.mLodSize[0];
+ *bytes += header.mLodSize[1];
+ *bytes += header.mLodSize[2];
+ *bytes += header.mLodSize[3];
}
if (bytes_visible)
@@ -4497,7 +4502,7 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* byte
lod = LLMeshRepository::getActualMeshLOD(header, lod);
if (lod >= 0 && lod <= 3)
{
- *bytes_visible = header[header_lod[lod]]["size"].asInteger();
+ *bytes_visible = header.mLodSize[lod];
}
}
@@ -4539,33 +4544,29 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLSD& header, F32 radius, S32* byte
LLMeshCostData::LLMeshCostData()
{
- mSizeByLOD.resize(4);
- mEstTrisByLOD.resize(4);
-
std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0);
std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f);
}
-bool LLMeshCostData::init(const LLSD& header)
+bool LLMeshCostData::init(const LLMeshHeader& header)
{
- mSizeByLOD.resize(4);
- mEstTrisByLOD.resize(4);
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+
std::fill(mSizeByLOD.begin(), mSizeByLOD.end(), 0);
std::fill(mEstTrisByLOD.begin(), mEstTrisByLOD.end(), 0.f);
- S32 bytes_high = header["high_lod"]["size"].asInteger();
- S32 bytes_med = header["medium_lod"]["size"].asInteger();
+ S32 bytes_high = header.mLodSize[3];
+ S32 bytes_med = header.mLodSize[2];
if (bytes_med == 0)
{
bytes_med = bytes_high;
}
- S32 bytes_low = header["low_lod"]["size"].asInteger();
+ S32 bytes_low = header.mLodSize[1];
if (bytes_low == 0)
{
bytes_low = bytes_med;
}
- S32 bytes_lowest = header["lowest_lod"]["size"].asInteger();
+ S32 bytes_lowest = header.mLodSize[0];
if (bytes_lowest == 0)
{
bytes_lowest = bytes_low;
@@ -4700,6 +4701,7 @@ F32 LLMeshCostData::getTriangleBasedStreamingCost()
bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
data = LLMeshCostData();
if (mThread && mesh_id.notNull())
@@ -4708,11 +4710,11 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
{
- LLSD& header = iter->second.second;
+ LLMeshHeader& header = iter->second.second;
- bool header_invalid = (header.has("404")
- || !header.has("lowest_lod")
- || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION));
+ bool header_invalid = (header.m404
+ || header.mLodSize[0] <= 0
+ || header.mVersion > MAX_MESH_VERSION);
if (!header_invalid)
{
return getCostData(header, data);
@@ -4724,7 +4726,7 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
return false;
}
-bool LLMeshRepository::getCostData(LLSD& header, LLMeshCostData& data)
+bool LLMeshRepository::getCostData(LLMeshHeader& header, LLMeshCostData& data)
{
data = LLMeshCostData();
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 6922367ff7..619e076fa6 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -194,6 +194,63 @@ private:
LLFrameTimer mTimer;
};
+class LLMeshHeader
+{
+public:
+
+ LLMeshHeader() {}
+
+ explicit LLMeshHeader(const LLSD& header)
+ {
+ fromLLSD(header);
+ }
+
+ void fromLLSD(const LLSD& header)
+ {
+ const char* lod[] =
+ {
+ "lowest_lod",
+ "low_lod",
+ "medium_lod",
+ "high_lod"
+ };
+
+ mVersion = header["version"].asInteger();
+
+ for (U32 i = 0; i < 4; ++i)
+ {
+ mLodOffset[i] = header[lod[i]]["offset"].asInteger();
+ mLodSize[i] = header[lod[i]]["size"].asInteger();
+ }
+
+ mSkinOffset = header["skin"]["offset"].asInteger();
+ mSkinSize = header["skin"]["size"].asInteger();
+
+ mPhysicsConvexOffset = header["physics_convex"]["offset"].asInteger();
+ mPhysicsConvexSize = header["physics_convex"]["size"].asInteger();
+
+ mPhysicsMeshOffset = header["physics_mesh"]["offset"].asInteger();
+ mPhysicsMeshSize = header["physics_mesh"]["size"].asInteger();
+
+ m404 = header.has("404");
+ }
+
+ S32 mVersion = -1;
+ S32 mSkinOffset = -1;
+ S32 mSkinSize = -1;
+
+ S32 mPhysicsConvexOffset = -1;
+ S32 mPhysicsConvexSize = -1;
+
+ S32 mPhysicsMeshOffset = -1;
+ S32 mPhysicsMeshSize = -1;
+
+ S32 mLodOffset[4] = { -1 };
+ S32 mLodSize[4] = { -1 };
+
+ bool m404 = false;
+};
+
class LLMeshRepoThread : public LLThread
{
public:
@@ -210,7 +267,7 @@ public:
LLCondition* mSignal;
//map of known mesh headers
- typedef boost::unordered_map<LLUUID, std::pair<U32, LLSD>> mesh_header_map; // pair is header_size and data
+ typedef boost::unordered_map<LLUUID, std::pair<U32, LLMeshHeader>> mesh_header_map; // pair is header_size and data
mesh_header_map mMeshHeader;
class HeaderRequest : public RequestStats
@@ -497,7 +554,7 @@ class LLMeshCostData
public:
LLMeshCostData();
- bool init(const LLSD& header);
+ bool init(const LLMeshHeader& header);
// Size for given LOD
S32 getSizeByLOD(S32 lod);
@@ -532,10 +589,10 @@ public:
private:
// From the "size" field of the mesh header. LOD 0=lowest, 3=highest.
- std::vector<S32> mSizeByLOD;
+ std::array<S32,4> mSizeByLOD;
// Estimated triangle counts derived from the LOD sizes. LOD 0=lowest, 3=highest.
- std::vector<F32> mEstTrisByLOD;
+ std::array<F32,4> mEstTrisByLOD;
};
class LLMeshRepository
@@ -566,9 +623,9 @@ public:
F32 getEstTrianglesMax(LLUUID mesh_id);
F32 getEstTrianglesStreamingCost(LLUUID mesh_id);
F32 getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
- static F32 getStreamingCostLegacy(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
+ static F32 getStreamingCostLegacy(LLMeshHeader& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
bool getCostData(LLUUID mesh_id, LLMeshCostData& data);
- bool getCostData(LLSD& header, LLMeshCostData& data);
+ bool getCostData(LLMeshHeader& header, LLMeshCostData& data);
LLMeshRepository();
@@ -588,7 +645,7 @@ public:
void notifyDecompositionReceived(LLModel::Decomposition* info);
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
- static S32 getActualMeshLOD(LLSD& header, S32 lod);
+ static S32 getActualMeshLOD(LLMeshHeader& header, S32 lod);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
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/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp
index 23e4fa8887..f6e501f147 100644
--- a/indra/newview/llpanelpresetspulldown.cpp
+++ b/indra/newview/llpanelpresetspulldown.cpp
@@ -34,6 +34,7 @@
#include "llbutton.h"
#include "lltabcontainer.h"
#include "llfloater.h"
+#include "llfloaterperformance.h"
#include "llfloaterreg.h"
#include "llpresetsmanager.h"
#include "llsliderctrl.h"
@@ -50,6 +51,7 @@ LLPanelPresetsPulldown::LLPanelPresetsPulldown()
mHoverTimer.stop();
mCommitCallbackRegistrar.add("Presets.GoGraphicsPrefs", boost::bind(&LLPanelPresetsPulldown::onGraphicsButtonClick, this, _2));
+ mCommitCallbackRegistrar.add("Presets.GoAutofpsPrefs", boost::bind(&LLPanelPresetsPulldown::onAutofpsButtonClick, this, _2));
mCommitCallbackRegistrar.add("Presets.RowClick", boost::bind(&LLPanelPresetsPulldown::onRowClick, this, _2));
buildFromFile( "panel_presets_pulldown.xml");
@@ -157,3 +159,13 @@ void LLPanelPresetsPulldown::onGraphicsButtonClick(const LLSD& user_data)
}
}
}
+
+void LLPanelPresetsPulldown::onAutofpsButtonClick(const LLSD& user_data)
+{
+ setVisible(FALSE);
+ LLFloaterPerformance* performance_floater = LLFloaterReg::showTypedInstance<LLFloaterPerformance>("performance");
+ if (performance_floater)
+ {
+ performance_floater->showAutoadjustmentsPanel();
+ }
+}
diff --git a/indra/newview/llpanelpresetspulldown.h b/indra/newview/llpanelpresetspulldown.h
index c0d32b9b21..79bd6886b1 100644
--- a/indra/newview/llpanelpresetspulldown.h
+++ b/indra/newview/llpanelpresetspulldown.h
@@ -41,6 +41,7 @@ class LLPanelPresetsPulldown : public LLPanelPulldown
private:
void onGraphicsButtonClick(const LLSD& user_data);
+ void onAutofpsButtonClick(const LLSD& user_data);
void onRowClick(const LLSD& user_data);
std::list<std::string> mPresetNames;
diff --git a/indra/newview/llperfstats.cpp b/indra/newview/llperfstats.cpp
new file mode 100644
index 0000000000..395ac0e788
--- /dev/null
+++ b/indra/newview/llperfstats.cpp
@@ -0,0 +1,566 @@
+/**
+* @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 "llviewerwindow.h"
+#include "llvoavatar.h"
+#include "llwindow.h"
+#include "llworld.h"
+#include <llthread.h>
+
+extern LLControlGroup gSavedSettings;
+
+namespace LLPerfStats
+{
+ // avatar timing metrics in ms (updated once per mainloop iteration)
+ std::atomic<F32> sTotalAvatarTime = 0.f;
+ std::atomic<F32> sAverageAvatarTime = 0.f;
+ std::atomic<F32> sMaxAvatarTime = 0.f;
+
+ 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};
+ U32 lastSleepedFrame{0};
+ U64 meanFrameTime{0};
+ std::mutex bufferToggleLock{};
+
+ F64 cpu_hertz{0.0};
+ U32 vsync_max_fps{60};
+
+ Tunables tunables;
+
+ std::atomic<int> StatsRecorder::writeBuffer{0};
+ bool StatsRecorder::collectionEnabled{true};
+ LLUUID StatsRecorder::focusAv{LLUUID::null};
+ bool StatsRecorder::autotuneInit{false};
+ 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); };
+ // 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.vsyncEnabled = gSavedSettings.getBOOL("RenderVSyncEnable");
+
+ LLPerfStats::tunables.userAutoTuneLock = gSavedSettings.getBOOL("AutoTuneLock") && gSavedSettings.getU32("KeepAutoTuneLock");
+
+ if(gSavedSettings.getBOOL("AutoTuneLock") && !gSavedSettings.getU32("KeepAutoTuneLock"))
+ {
+ gSavedSettings.setBOOL("AutoTuneLock", FALSE);
+ }
+
+ LLPerfStats::tunables.userAutoTuneEnabled = LLPerfStats::tunables.userAutoTuneLock;
+
+ if (LLPerfStats::tunables.userAutoTuneEnabled && !gSavedSettings.getBOOL("AutoTuneFPS"))
+ {
+ gSavedSettings.setBOOL("AutoTuneFPS", TRUE);
+ }
+
+ // Note: The Max ART slider is logarithmic and thus we have an intermediate proxy value
+ updateRenderCostLimitFromSettings();
+ resetChanges();
+ }
+
+ StatsRecorder::StatsRecorder():q(1024*16)
+ {
+ // create a queue
+ tunables.initialiseFromSettings();
+ LLPerfStats::cpu_hertz = (F64)LLTrace::BlockTimer::countsPerSecond();
+ LLPerfStats::vsync_max_fps = gViewerWindow->getWindow()->getRefreshRate();
+ }
+
+ // 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 };
+
+#if 0
+ static constexpr std::initializer_list<StatType_t> avatarStatsToAvg = {
+ StatType_t::RENDER_GEOMETRY,
+ StatType_t::RENDER_SHADOWS,
+ StatType_t::RENDER_COMBINED,
+ StatType_t::RENDER_IDLE };
+#endif
+
+
+ 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;
+ }
+ }
+
+ // 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(autotuneInit && 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);
+ }
+ }
+
+ // called once per main loop iteration on main thread
+ void updateClass()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+
+ sTotalAvatarTime = LLVOAvatar::getTotalGPURenderTime();
+ sAverageAvatarTime = LLVOAvatar::getAverageGPURenderTime();
+ sMaxAvatarTime = LLVOAvatar::getMaxGPURenderTime();
+
+ auto general = LL::WorkQueue::getInstance("General");
+
+ if (general)
+ {
+ general->post([] { StatsRecorder::update(); });
+ }
+ }
+
+ // called once per main loop iteration on General thread
+ void StatsRecorder::update()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ StatsRecord upd;
+ auto& instance{ StatsRecorder::getInstance() };
+
+ while (enabled() && !LLApp::isQuitting() && instance.q.tryPop(upd))
+ {
+ instance.processUpdate(upd);
+ }
+ }
+
+ //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();
+ }
+
+ const U32 NUM_PERIODS = 50;
+ void StatsRecorder::updateMeanFrameTime(U64 cur_frame_time_raw)
+ {
+ static std::deque<U64> frame_time_deque;
+ frame_time_deque.push_front(cur_frame_time_raw);
+ if (frame_time_deque.size() > NUM_PERIODS)
+ {
+ frame_time_deque.pop_back();
+ }
+
+ std::vector<U64> buf(frame_time_deque.begin(), frame_time_deque.end());
+ std::sort(buf.begin(), buf.end());
+
+ LLPerfStats::meanFrameTime = (buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2];
+ }
+ U64 StatsRecorder::getMeanTotalFrameTime()
+ {
+ return LLPerfStats::meanFrameTime;
+ }
+
+ // static
+ void StatsRecorder::updateAvatarParams()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+
+ if(tunables.autoTuneTimeout)
+ {
+ LLPerfStats::lastSleepedFrame = gFrameCount;
+ tunables.autoTuneTimeout = false;
+ return;
+ }
+ // 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;
+ LLPerfStats::lastSleepedFrame = gFrameCount;
+ return;
+ }
+
+ U32 target_fps = tunables.vsyncEnabled ? std::min(LLPerfStats::vsync_max_fps, tunables.userTargetFPS) : tunables.userTargetFPS;
+
+ if(LLPerfStats::lastSleepedFrame != 0)
+ {
+ // wait a short time after viewer regains focus
+ if((gFrameCount - LLPerfStats::lastSleepedFrame) > target_fps * 5)
+ {
+ LLPerfStats::lastSleepedFrame = 0;
+ }
+ else
+ {
+ return;
+ }
+ }
+ updateMeanFrameTime(tot_frame_time_raw);
+
+ 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 = ms_to_raw(sMaxAvatarTime);
+ // 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 = ms_to_raw(sTotalAvatarTime);
+
+ // The frametime budget we have based on the target FPS selected
+ auto target_frame_time_raw = (U64)llround(LLPerfStats::cpu_hertz / (target_fps == 0 ? 1 : target_fps));
+ // 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 > 50?inferredFPS:50};
+ /*if( tot_limit_time_raw != 0)
+ {
+ // This could be problematic.
+ tot_frame_time_raw -= tot_limit_time_raw;
+ }*/
+
+ F64 time_buf = target_frame_time_raw * 0.1;
+
+ // 1) Is the target frame time lower than current?
+ if ((target_frame_time_raw + time_buf) <= tot_frame_time_raw)
+ {
+ if (target_frame_time_raw - time_buf >= getMeanTotalFrameTime())
+ {
+ belowTargetFPS = false;
+ LLPerfStats::lastGlobalPrefChange = gFrameCount;
+ return;
+ }
+
+ 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 ? tot_frame_time_raw - tot_avatar_time_raw : 0;
+
+ // 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_AVATARS_ONLY)
+ {
+ // 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 0 // TODO RenderReflectionDetail went away
+ 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
+#endif
+ {
+ // 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) && (tunables.userFPSTuningStrategy != TUNE_SCENE_ONLY))
+ {
+ // 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;
+ }
+
+ if (new_render_limit_ns > LLPerfStats::ART_MIN_ADJUST_DOWN_NANOS)
+ {
+ 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) ) ||
+ (tunables.vsyncEnabled && (target_fps == LLPerfStats::vsync_max_fps) && (target_frame_time_raw > getMeanTotalFrameTime())))
+ {
+ 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(renderAvatarMaxART_ns != 0 && LLPerfStats::tunedAvatars > 0 && (tunables.userFPSTuningStrategy != TUNE_SCENE_ONLY) )
+ {
+ // if we have more time to spare let's shift up little in the hope we'll restore an avatar.
+ U64 up_step = LLPerfStats::tunedAvatars > 2 ? LLPerfStats::ART_MIN_ADJUST_UP_NANOS : LLPerfStats::ART_MIN_ADJUST_UP_NANOS * 2;
+ renderAvatarMaxART_ns += up_step;
+ tunables.updateSettingsFromRenderCostLimit();
+ return;
+ }
+ if(tunables.userFPSTuningStrategy != TUNE_AVATARS_ONLY)
+ {
+ 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.
+# if 0 // RenderReflectionDetail went away
+ LLPerfStats::tunables.updateReflectionDetail( std::min(LLPipeline::RenderReflectionDetail + 1, tunables.userTargetReflections) );
+#endif
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h
new file mode 100644
index 0000000000..bb5677f237
--- /dev/null
+++ b/indra/newview/llperfstats.h
@@ -0,0 +1,350 @@
+/**
+* @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
+{
+
+ // called once per main loop iteration
+ void updateClass();
+
+// 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{5000};
+ 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};
+ static constexpr U32 TUNE_SCENE_ONLY{2};
+
+ extern F64 cpu_hertz;
+
+ extern std::atomic<int64_t> tunedAvatars;
+ extern std::atomic<U64> renderAvatarMaxART_ns;
+ extern bool belowTargetFPS;
+ extern U32 lastGlobalPrefChange;
+ extern U32 lastSleepedFrame;
+ extern U64 meanFrameTime;
+ extern std::mutex bufferToggleLock;
+
+ enum class ObjType_t{
+ OT_GENERAL=0, // Also Unknown. Used for n/a type stats such as scenery
+ 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 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};
+ bool autoTuneTimeout{true};
+ bool vsyncEnabled{true};
+
+ 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 resetChanges(){tuningFlag=Nothing;};
+ void initialiseFromSettings();
+ void updateRenderCostLimitFromSettings();
+ void updateSettingsFromRenderCostLimit();
+ void applyUpdates();
+ };
+
+ extern Tunables tunables;
+
+ class StatsRecorder{
+ using Queue = LLThreadSafeQueue<StatsRecord>;
+ public:
+
+ // called once per main loop iteration on General thread
+ static void update();
+
+ 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 setAutotuneInit(){autotuneInit = true;};
+ 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);
+ static U64 getMeanTotalFrameTime();
+ static void updateMeanFrameTime(U64 tot_frame_time_raw);
+// 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 bool autotuneInit;
+ 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
+
+ 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 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;
+ }
+ }
+
+ 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();
+
+ Queue q;
+
+ ~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;
+ };
+
+ ~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) / LLPerfStats::cpu_hertz; };
+ inline double raw_to_us(U64 raw) { return (static_cast<double>(raw) * 1000000.0) / LLPerfStats::cpu_hertz; };
+ inline double raw_to_ms(U64 raw) { return (static_cast<double>(raw) * 1000.0) / LLPerfStats::cpu_hertz; };
+
+ inline U64 ns_to_raw(double ns) { return (U64)(LLPerfStats::cpu_hertz * (ns / 1000000000.0)); }
+ inline U64 us_to_raw(double us) { return (U64)(LLPerfStats::cpu_hertz * (us / 1000000.0)); }
+ inline U64 ms_to_raw(double ms) { return (U64)(LLPerfStats::cpu_hertz * (ms / 1000.0));
+
+ }
+
+
+ using RecordSceneTime = RecordTime<ObjType_t::OT_GENERAL>;
+
+};// namespace LLPerfStats
+
+#endif
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index 803f7bdc97..7ea0fe6187 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -78,8 +78,12 @@ public:
// point at which environment map was last generated from (in agent space)
LLVector4a mOrigin;
- // distance from viewer camera
- F32 mDistance;
+ // distance from main viewer camera
+ F32 mDistance = -1.f;
+
+ // Minimum and maximum depth in current render camera
+ F32 mMinDepth = -1.f;
+ F32 mMaxDepth = -1.f;
// radius of this probe's affected area
F32 mRadius = 16.f;
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 88edbc9224..2235453e47 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -45,10 +45,13 @@ extern U32 nhpo2(U32 v);
static void touch_default_probe(LLReflectionMap* probe)
{
- LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
- origin.mV[2] += 64.f;
+ if (LLViewerCamera::getInstance())
+ {
+ LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
+ origin.mV[2] += 64.f;
- probe->mOrigin.load3(origin.mV);
+ probe->mOrigin.load3(origin.mV);
+ }
}
LLReflectionMapManager::LLReflectionMapManager()
@@ -58,17 +61,17 @@ LLReflectionMapManager::LLReflectionMapManager()
void LLReflectionMapManager::initCubeFree()
{
+ // start at 1 because index 0 is reserved for mDefaultProbe
for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i)
{
- mCubeFree[i] = true;
+ mCubeFree.push_back(i);
}
-
- // cube index 0 is reserved for the fallback probe
- mCubeFree[0] = false;
}
struct CompareProbeDistance
{
+ LLReflectionMap* mDefaultProbe;
+
bool operator()(const LLPointer<LLReflectionMap>& lhs, const LLPointer<LLReflectionMap>& rhs)
{
return lhs->mDistance < rhs->mDistance;
@@ -83,7 +86,15 @@ static F32 update_score(LLReflectionMap* p)
// return true if a is higher priority for an update than b
static bool check_priority(LLReflectionMap* a, LLReflectionMap* b)
{
- if (!a->mComplete && !b->mComplete)
+ if (a->mCubeIndex == -1)
+ { // not a candidate for updating
+ return false;
+ }
+ else if (b->mCubeIndex == -1)
+ { // certainly higher priority than b
+ return true;
+ }
+ else if (!a->mComplete && !b->mComplete)
{ //neither probe is complete, use distance
return a->mDistance < b->mDistance;
}
@@ -133,14 +144,7 @@ void LLReflectionMapManager::update()
}
}
-
- if (mDefaultProbe.isNull())
- {
- mDefaultProbe = addProbe();
- mDefaultProbe->mDistance = -4096.f; // hack to make sure the default probe is always first in sort order
- mDefaultProbe->mRadius = 4096.f;
- touch_default_probe(mDefaultProbe);
- }
+ llassert(mProbes[0] == mDefaultProbe);
LLVector4a camera_pos;
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
@@ -170,6 +174,7 @@ void LLReflectionMapManager::update()
return;
}
+
bool did_update = false;
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
@@ -188,7 +193,46 @@ void LLReflectionMapManager::update()
doProbeUpdate();
}
- //LL_INFOS() << mProbes.size() << LL_ENDL;
+ // update distance to camera for all probes
+ std::sort(mProbes.begin()+1, mProbes.end(), CompareProbeDistance());
+ llassert(mProbes[0] == mDefaultProbe);
+ llassert(mProbes[0]->mCubeArray == mTexture);
+ llassert(mProbes[0]->mCubeIndex == 0);
+
+ // make sure we're assigning cube slots to the closest probes
+
+ // first free any cube indices for distant probes
+ for (U32 i = mReflectionProbeCount; i < mProbes.size(); ++i)
+ {
+ LLReflectionMap* probe = mProbes[i];
+ llassert(probe != nullptr);
+
+ if (probe->mCubeIndex != -1 && mUpdatingProbe != probe)
+ { // free this index
+ mCubeFree.push_back(probe->mCubeIndex);
+
+ probe->mCubeArray = nullptr;
+ probe->mCubeIndex = -1;
+ probe->mComplete = false;
+ }
+ }
+
+ // next distribute the free indices
+ U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size());
+
+ for (S32 i = 1; i < count && !mCubeFree.empty(); ++i)
+ {
+ // find the closest probe that needs a cube index
+ LLReflectionMap* probe = mProbes[i];
+
+ if (probe->mCubeIndex == -1)
+ {
+ S32 idx = allocateCubeIndex();
+ llassert(idx > 0); //if we're still in this loop, mCubeFree should not be empty and allocateCubeIndex should be returning good indices
+ probe->mCubeArray = mTexture;
+ probe->mCubeIndex = idx;
+ }
+ }
for (int i = 0; i < mProbes.size(); ++i)
{
@@ -205,8 +249,6 @@ void LLReflectionMapManager::update()
continue;
}
- probe->mProbeIndex = i;
-
LLVector4a d;
if (probe != mDefaultProbe)
@@ -219,6 +261,10 @@ void LLReflectionMapManager::update()
// make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once)
probe->mDistance = 64.f;
}
+ else
+ {
+ probe->mDistance = -4096.f; //boost priority of default probe when it's not complete
+ }
if (probe->mComplete)
{
@@ -288,13 +334,8 @@ void LLReflectionMapManager::update()
if (!did_update && oldestProbe != nullptr)
{
LLReflectionMap* probe = oldestProbe;
- if (probe->mCubeIndex == -1)
- {
- probe->mCubeArray = mTexture;
-
- probe->mCubeIndex = probe == mDefaultProbe ? 0 : allocateCubeIndex();
- }
-
+ llassert(probe->mCubeIndex != -1);
+
probe->autoAdjustOrigin();
mUpdatingProbe = probe;
@@ -307,10 +348,6 @@ void LLReflectionMapManager::update()
oldestOccluded->autoAdjustOrigin();
oldestOccluded->mLastUpdateTime = gFrameTimeSeconds;
}
-
- // update distance to camera for all probes
- mDefaultProbe->mDistance = -4096.f; // make default probe always end up at index 0
- std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
}
LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
@@ -318,6 +355,14 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
LLReflectionMap* probe = new LLReflectionMap();
probe->mGroup = group;
+ if (mDefaultProbe.isNull())
+ { //safety check to make sure default probe is always first probe added
+ mDefaultProbe = new LLReflectionMap();
+ mProbes.push_back(mDefaultProbe);
+ }
+
+ llassert(mProbes[0] == mDefaultProbe);
+
if (group)
{
probe->mOrigin = group->getOctreeNode()->getCenter();
@@ -335,10 +380,22 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
return probe;
}
+struct CompareProbeDepth
+{
+ bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs)
+ {
+ return lhs->mMinDepth < rhs->mMinDepth;
+ }
+};
+
void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& maps)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LLMatrix4a modelview;
+ modelview.loadu(gGLModelView);
+ LLVector4a oa; // scratch space for transformed origin
+
U32 count = 0;
U32 lastIdx = 0;
for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i)
@@ -348,8 +405,10 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma
{
if (!mProbes[i]->mOccluded && mProbes[i]->mComplete)
{
- mProbes[i]->mProbeIndex = count;
maps[count++] = mProbes[i];
+ modelview.affineTransform(mProbes[i]->mOrigin, oa);
+ mProbes[i]->mMinDepth = -oa.getF32ptr()[2] - mProbes[i]->mRadius;
+ mProbes[i]->mMaxDepth = -oa.getF32ptr()[2] + mProbes[i]->mRadius;
}
}
else
@@ -365,6 +424,16 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma
mProbes[i]->mProbeIndex = -1;
}
+ if (count > 1)
+ {
+ std::sort(maps.begin(), maps.begin() + count, CompareProbeDepth());
+ }
+
+ for (U32 i = 0; i < count; ++i)
+ {
+ maps[i]->mProbeIndex = i;
+ }
+
// null terminate list
if (count < maps.size())
{
@@ -407,32 +476,15 @@ LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vo
return probe;
}
-
S32 LLReflectionMapManager::allocateCubeIndex()
{
- for (int i = 0; i < mReflectionProbeCount; ++i)
+ if (!mCubeFree.empty())
{
- if (mCubeFree[i])
- {
- mCubeFree[i] = false;
- return i;
- }
+ S32 ret = mCubeFree.front();
+ mCubeFree.pop_front();
+ return ret;
}
- // no cubemaps free, steal one from the back of the probe list
- for (int i = mProbes.size() - 1; i >= mReflectionProbeCount; --i)
- {
- if (mProbes[i]->mCubeIndex != -1)
- {
- S32 ret = mProbes[i]->mCubeIndex;
- mProbes[i]->mCubeIndex = -1;
- mProbes[i]->mCubeArray = nullptr;
- mProbes[i]->mComplete = false;
- return ret;
- }
- }
-
- llassert(false); // should never fail to allocate, something is probably wrong with mCubeFree
return -1;
}
@@ -445,7 +497,7 @@ void LLReflectionMapManager::deleteProbe(U32 i)
if (probe->mCubeIndex != -1)
{ // mark the cube index used by this probe as being free
- mCubeFree[probe->mCubeIndex] = true;
+ mCubeFree.push_back(probe->mCubeIndex);
}
if (mUpdatingProbe == probe)
{
@@ -776,13 +828,14 @@ void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
}
// search for new neighbors
+ if (probe->isRelevant())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search");
for (auto& other : mProbes)
{
if (other != mDefaultProbe && other != probe)
{
- if (probe->intersects(other))
+ if (other->isRelevant() && probe->intersects(other))
{
probe->mNeighbors.push_back(other);
other->mNeighbors.push_back(probe);
@@ -816,6 +869,7 @@ void LLReflectionMapManager::updateUniforms()
// x - irradiance scale
// y - radiance scale
// z - fade in
+ // w - znear
LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT];
// indices used by probe:
@@ -828,6 +882,7 @@ void LLReflectionMapManager::updateUniforms()
// list of neighbor indices
GLint refNeighbor[4096];
+ GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
// numbrer of active refmaps
GLint refmapCount;
};
@@ -837,6 +892,17 @@ void LLReflectionMapManager::updateUniforms()
ReflectionProbeData rpd;
+ F32 minDepth[256];
+
+ for (int i = 0; i < 256; ++i)
+ {
+ rpd.refBucket[i][0] = mReflectionProbeCount;
+ rpd.refBucket[i][1] = mReflectionProbeCount;
+ rpd.refBucket[i][2] = mReflectionProbeCount;
+ rpd.refBucket[i][3] = mReflectionProbeCount;
+ minDepth[i] = FLT_MAX;
+ }
+
// load modelview matrix into matrix 4a
LLMatrix4a modelview;
modelview.loadu(gGLModelView);
@@ -861,6 +927,28 @@ void LLReflectionMapManager::updateUniforms()
break;
}
+ if (refmap != mDefaultProbe)
+ {
+ // bucket search data
+ // theory of operation:
+ // 1. Determine minimum and maximum depth of each influence volume and store in mDepth (done in getReflectionMaps)
+ // 2. Sort by minimum depth
+ // 3. Prepare a bucket for each 1m of depth out to 256m
+ // 4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket
+ // 5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence
+ // the current pixel.
+ int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255);
+ int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255);
+ for (U32 i = depth_min; i <= depth_max; ++i)
+ {
+ if (refmap->mMinDepth < minDepth[i])
+ {
+ minDepth[i] = refmap->mMinDepth;
+ rpd.refBucket[i][0] = refmap->mProbeIndex;
+ }
+ }
+ }
+
llassert(refmap->mProbeIndex == count);
llassert(mReflectionMaps[refmap->mProbeIndex] == refmap);
@@ -890,7 +978,11 @@ void LLReflectionMapManager::updateUniforms()
rpd.refIndex[count][3] = -rpd.refIndex[count][3];
}
- rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, radscale, refmap->mFadeIn, 0.f);
+ rpd.refParams[count].set(
+ llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale
+ radscale, // radiance scale
+ refmap->mFadeIn, // fade in weight
+ oa.getF32ptr()[2] - refmap->mRadius); // z near
S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
{
@@ -907,7 +999,7 @@ void LLReflectionMapManager::updateUniforms()
}
GLint idx = neighbor->mProbeIndex;
- if (idx == -1 || neighbor->mOccluded)
+ if (idx == -1 || neighbor->mOccluded || neighbor->mCubeIndex == -1)
{
continue;
}
@@ -944,6 +1036,30 @@ void LLReflectionMapManager::updateUniforms()
count++;
}
+#if 0
+ {
+ // fill in gaps in refBucket
+ S32 probe_idx = mReflectionProbeCount;
+
+ for (int i = 0; i < 256; ++i)
+ {
+ if (i < count)
+ { // for debugging, store depth of mReflectionsMaps[i]
+ rpd.refBucket[i][1] = (S32) (mReflectionMaps[i]->mDepth * 10);
+ }
+
+ if (rpd.refBucket[i][0] == mReflectionProbeCount)
+ {
+ rpd.refBucket[i][0] = probe_idx;
+ }
+ else
+ {
+ probe_idx = rpd.refBucket[i][0];
+ }
+ }
+ }
+#endif
+
rpd.refmapCount = count;
//copy rpd into uniform buffer object
@@ -958,6 +1074,21 @@ void LLReflectionMapManager::updateUniforms()
glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
+
+#if 0
+ if (!gCubeSnapshot)
+ {
+ for (auto& probe : mProbes)
+ {
+ LLViewerObject* vobj = probe->mViewerObject;
+ if (vobj)
+ {
+ F32 time = (F32)gFrameTimeSeconds - probe->mLastUpdateTime;
+ vobj->setDebugText(llformat("%d/%d/%d/%.1f - %.1f/%.1f", probe->mCubeIndex, probe->mProbeIndex, (U32) probe->mNeighbors.size(), probe->mMinDepth, probe->mMaxDepth, time), time > 1.f ? LLColor4::white : LLColor4::green);
+ }
+ }
+ }
+#endif
}
void LLReflectionMapManager::setUniforms()
@@ -977,37 +1108,40 @@ void LLReflectionMapManager::setUniforms()
void renderReflectionProbe(LLReflectionMap* probe)
{
- F32* po = probe->mOrigin.getF32ptr();
-
- //draw orange line from probe to neighbors
- gGL.flush();
- gGL.diffuseColor4f(1, 0.5f, 0, 1);
- gGL.begin(gGL.LINES);
- for (auto& neighbor : probe->mNeighbors)
+ if (probe->isRelevant())
{
- if (probe->mViewerObject && neighbor->mViewerObject)
- {
- continue;
- }
-
- gGL.vertex3fv(po);
- gGL.vertex3fv(neighbor->mOrigin.getF32ptr());
- }
- gGL.end();
- gGL.flush();
+ F32* po = probe->mOrigin.getF32ptr();
- gGL.diffuseColor4f(1, 1, 0, 1);
- gGL.begin(gGL.LINES);
- for (auto& neighbor : probe->mNeighbors)
- {
- if (probe->mViewerObject && neighbor->mViewerObject)
+ //draw orange line from probe to neighbors
+ gGL.flush();
+ gGL.diffuseColor4f(1, 0.5f, 0, 1);
+ gGL.begin(gGL.LINES);
+ for (auto& neighbor : probe->mNeighbors)
{
+ if (probe->mViewerObject && neighbor->mViewerObject)
+ {
+ continue;
+ }
+
gGL.vertex3fv(po);
gGL.vertex3fv(neighbor->mOrigin.getF32ptr());
}
+ gGL.end();
+ gGL.flush();
+
+ gGL.diffuseColor4f(1, 1, 0, 1);
+ gGL.begin(gGL.LINES);
+ for (auto& neighbor : probe->mNeighbors)
+ {
+ if (probe->mViewerObject && neighbor->mViewerObject)
+ {
+ gGL.vertex3fv(po);
+ gGL.vertex3fv(neighbor->mOrigin.getF32ptr());
+ }
+ }
+ gGL.end();
+ gGL.flush();
}
- gGL.end();
- gGL.flush();
#if 0
LLSpatialGroup* group = probe->mGroup;
@@ -1095,7 +1229,6 @@ void LLReflectionMapManager::initReflectionMaps()
mUpdatingProbe = nullptr;
mRadiancePass = false;
mRealtimeRadiancePass = false;
- mDefaultProbe = nullptr;
for (auto& probe : mProbes)
{
@@ -1104,14 +1237,28 @@ void LLReflectionMapManager::initReflectionMaps()
probe->mProbeIndex = -1;
probe->mCubeArray = nullptr;
probe->mCubeIndex = -1;
+ probe->mNeighbors.clear();
}
- for (bool& is_free : mCubeFree)
+ mCubeFree.clear();
+ initCubeFree();
+
+ if (mDefaultProbe.isNull())
{
- is_free = true;
+ llassert(mProbes.empty()); // default probe MUST be the first probe created
+ mDefaultProbe = new LLReflectionMap();
+ mProbes.push_back(mDefaultProbe);
}
- mCubeFree[0] = false;
+ llassert(mProbes[0] == mDefaultProbe);
+
+ mDefaultProbe->mCubeIndex = 0;
+ mDefaultProbe->mCubeArray = mTexture;
+ mDefaultProbe->mDistance = 64.f;
+ mDefaultProbe->mRadius = 4096.f;
+ mDefaultProbe->mProbeIndex = 0;
+ touch_default_probe(mDefaultProbe);
+
}
if (mVertexBuffer.isNull())
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 234bde51a8..c0618de410 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -110,7 +110,7 @@ private:
void deleteProbe(U32 i);
// get a free cube index
- // if no cube indices are free, free one starting from the back of the probe list
+ // returns -1 if allocation failed
S32 allocateCubeIndex();
// update the neighbors of the given probe
@@ -137,12 +137,9 @@ private:
// storage for reflection probe irradiance maps
LLPointer<LLCubeMapArray> mIrradianceMaps;
- // array indicating if a particular cubemap is free
- bool mCubeFree[LL_MAX_REFLECTION_PROBE_COUNT];
+ // list of free cubemap indices
+ std::list<S32> mCubeFree;
- // start tracking the given spatial group
- void trackGroup(LLSpatialGroup* group);
-
// perform an update on the currently updating Probe
void doProbeUpdate();
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 22c1176b05..71dcc56197 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2188,8 +2188,8 @@ void LLSelectMgr::selectionRevertGLTFMaterials()
// Enqueue update to server
if (asset_id.notNull())
{
- // Restore overrides
- LLGLTFMaterialList::queueModify(objectp, te, nodep->mSavedGLTFOverrideMaterials[te]);
+ // Restore overrides and base material
+ LLGLTFMaterialList::queueApply(objectp, te, asset_id, nodep->mSavedGLTFOverrideMaterials[te]);
}
else
{
@@ -5797,7 +5797,7 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
if (can_copy && can_transfer && node->getObject()->getVolume())
{
uuid_vec_t material_ids;
- gltf_materials_vec_t materials;
+ gltf_materials_vec_t override_materials;
LLVOVolume* vobjp = (LLVOVolume*)node->getObject();
for (int i = 0; i < vobjp->getNumTEs(); ++i)
{
@@ -5812,18 +5812,16 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
if (old_override)
{
LLPointer<LLGLTFMaterial> mat = new LLGLTFMaterial(*old_override);
- materials.push_back(mat);
+ override_materials.push_back(mat);
}
else
{
- materials.push_back(nullptr);
+ override_materials.push_back(nullptr);
}
}
- node->saveGLTFMaterialIds(material_ids);
-
// processObjectProperties does not include overrides so this
// might need to be moved to LLGLTFMaterialOverrideDispatchHandler
- node->saveGLTFOverrideMaterials(materials);
+ node->saveGLTFMaterials(material_ids, override_materials);
}
}
@@ -6576,8 +6574,7 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
}
saveTextures(nodep.mSavedTextures);
- saveGLTFMaterialIds(nodep.mSavedGLTFMaterialIds);
- saveGLTFOverrideMaterials(nodep.mSavedGLTFOverrideMaterials);
+ saveGLTFMaterials(nodep.mSavedGLTFMaterialIds, nodep.mSavedGLTFOverrideMaterials);
}
LLSelectNode::~LLSelectNode()
@@ -6711,28 +6708,21 @@ void LLSelectNode::saveTextures(const uuid_vec_t& textures)
}
}
-void LLSelectNode::saveGLTFMaterialIds(const uuid_vec_t& materials)
+void LLSelectNode::saveGLTFMaterials(const uuid_vec_t& materials, const gltf_materials_vec_t& override_materials)
{
if (mObject.notNull())
{
mSavedGLTFMaterialIds.clear();
+ mSavedGLTFOverrideMaterials.clear();
for (uuid_vec_t::const_iterator materials_it = materials.begin();
materials_it != materials.end(); ++materials_it)
{
mSavedGLTFMaterialIds.push_back(*materials_it);
}
- }
-}
-
-void LLSelectNode::saveGLTFOverrideMaterials(const gltf_materials_vec_t& materials)
-{
- if (mObject.notNull())
- {
- mSavedGLTFOverrideMaterials.clear();
- for (gltf_materials_vec_t::const_iterator mat_it = materials.begin();
- mat_it != materials.end(); ++mat_it)
+ for (gltf_materials_vec_t::const_iterator mat_it = override_materials.begin();
+ mat_it != override_materials.end(); ++mat_it)
{
mSavedGLTFOverrideMaterials.push_back(*mat_it);
}
@@ -7833,7 +7823,7 @@ S32 LLObjectSelection::getSelectedObjectRenderCost()
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
{
// add the cost of each individual texture in the linkset
- cost += iter->second;
+ cost += LLVOVolume::getTextureCost(*iter);
}
textures.clear();
@@ -7855,7 +7845,7 @@ S32 LLObjectSelection::getSelectedObjectRenderCost()
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
{
// add the cost of each individual texture in the linkset
- cost += iter->second;
+ cost += LLVOVolume::getTextureCost(*iter);
}
textures.clear();
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 3ee78f9a58..ca9a32f0db 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -197,8 +197,7 @@ public:
// final gltf material that users see.
// Ids get applied and restored by tools floater,
// overrides get applied in live material editor
- void saveGLTFMaterialIds(const uuid_vec_t& materials);
- void saveGLTFOverrideMaterials(const gltf_materials_vec_t& materials);
+ void saveGLTFMaterials(const uuid_vec_t& materials, const gltf_materials_vec_t& override_materials);
BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const;
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 1427dbefa1..a7a5a9223c 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -574,11 +574,11 @@ void LLSettingsVOSky::convertAtmosphericsToLegacy(LLSD& legacy, LLSD& settings)
legacy[SETTING_BLUE_DENSITY] = ensure_array_4(legacyhaze[SETTING_BLUE_DENSITY], 1.0);
legacy[SETTING_BLUE_HORIZON] = ensure_array_4(legacyhaze[SETTING_BLUE_HORIZON], 1.0);
- legacy[SETTING_DENSITY_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
- legacy[SETTING_DISTANCE_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_DENSITY_MULTIPLIER] = llsd::array(legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal(), 0.0f, 0.0f, 1.0f);
+ legacy[SETTING_DISTANCE_MULTIPLIER] = llsd::array(legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal(), 0.0f, 0.0f, 1.0f);
- legacy[SETTING_HAZE_DENSITY] = LLSDArray(legacyhaze[SETTING_HAZE_DENSITY])(0.0f)(0.0f)(1.0f);
- legacy[SETTING_HAZE_HORIZON] = LLSDArray(legacyhaze[SETTING_HAZE_HORIZON])(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_HAZE_DENSITY] = llsd::array(legacyhaze[SETTING_HAZE_DENSITY], 0.0f, 0.0f, 1.0f);
+ legacy[SETTING_HAZE_HORIZON] = llsd::array(legacyhaze[SETTING_HAZE_HORIZON], 0.0f, 0.0f, 1.0f);
}
}
@@ -592,15 +592,15 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA
legacy[SETTING_CLOUD_COLOR] = ensure_array_4(settings[SETTING_CLOUD_COLOR], 1.0);
legacy[SETTING_CLOUD_POS_DENSITY1] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY1], 1.0);
legacy[SETTING_CLOUD_POS_DENSITY2] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY2], 1.0);
- legacy[SETTING_CLOUD_SCALE] = LLSDArray(settings[SETTING_CLOUD_SCALE])(LLSD::Real(0.0))(LLSD::Real(0.0))(LLSD::Real(1.0));
+ legacy[SETTING_CLOUD_SCALE] = llsd::array(settings[SETTING_CLOUD_SCALE], LLSD::Real(0.0), LLSD::Real(0.0), LLSD::Real(1.0));
legacy[SETTING_CLOUD_SCROLL_RATE] = settings[SETTING_CLOUD_SCROLL_RATE];
- legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = LLSDArray(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())))
- (LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));
- legacy[SETTING_CLOUD_SHADOW] = LLSDArray(settings[SETTING_CLOUD_SHADOW].asReal())(0.0f)(0.0f)(1.0f);
- legacy[SETTING_GAMMA] = LLSDArray(settings[SETTING_GAMMA])(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = llsd::array(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())),
+ LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));
+ legacy[SETTING_CLOUD_SHADOW] = llsd::array(settings[SETTING_CLOUD_SHADOW].asReal(), 0.0f, 0.0f, 1.0f);
+ legacy[SETTING_GAMMA] = llsd::array(settings[SETTING_GAMMA], 0.0f, 0.0f, 1.0f);
legacy[SETTING_GLOW] = ensure_array_4(settings[SETTING_GLOW], 1.0);
legacy[SETTING_LIGHT_NORMAL] = ensure_array_4(psky->getLightDirection().getValue(), 0.0f);
- legacy[SETTING_MAX_Y] = LLSDArray(settings[SETTING_MAX_Y])(0.0f)(0.0f)(1.0f);
+ legacy[SETTING_MAX_Y] = llsd::array(settings[SETTING_MAX_Y], 0.0f, 0.0f, 1.0f);
legacy[SETTING_STAR_BRIGHTNESS] = settings[SETTING_STAR_BRIGHTNESS].asReal() / 250.0f; // convert from 0-500 -> 0-2 ala pre-FS-compat changes
legacy[SETTING_SUNLIGHT_COLOR] = ensure_array_4(settings[SETTING_SUNLIGHT_COLOR], 1.0f);
@@ -1113,7 +1113,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &n
newsettings[SETTING_NAME] = name;
- LLSD watertrack = LLSDArray(
+ LLSD watertrack = llsd::array(
LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
(SETTING_KEYNAME, "water:Default"));
@@ -1128,7 +1128,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &n
skytrack.append(entry);
}
- newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
+ newsettings[SETTING_TRACKS] = llsd::array(watertrack, skytrack);
LLSD frames(LLSD::emptyMap());
@@ -1216,7 +1216,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regio
watersettings[SETTING_NAME] = watername;
frames[watername] = watersettings;
- LLSD watertrack = LLSDArray(
+ LLSD watertrack = llsd::array(
LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
(SETTING_KEYNAME, watername));
@@ -1230,7 +1230,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regio
LLSD newsettings = LLSDMap
( SETTING_NAME, "Region (legacy)" )
- ( SETTING_TRACKS, LLSDArray(watertrack)(skytrack))
+ ( SETTING_TRACKS, llsd::array(watertrack, skytrack))
( SETTING_FRAMES, frames )
( SETTING_TYPE, "daycycle" );
@@ -1411,7 +1411,7 @@ LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
skys[name.str()] = std::static_pointer_cast<LLSettingsSky>((*it).second);
F32 frame = ((tracksky.size() == 1) && (it == tracksky.begin())) ? -1.0f : (*it).first;
- llsdcycle.append( LLSDArray(LLSD::Real(frame))(name.str()) );
+ llsdcycle.append( llsd::array(LLSD::Real(frame), name.str()) );
}
LLSD llsdskylist(LLSD::emptyMap());
@@ -1424,7 +1424,7 @@ LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
llsdskylist[(*its).first] = llsdsky;
}
- return LLSDArray(LLSD::emptyMap())(llsdcycle)(llsdskylist)(llsdwater);
+ return llsd::array(LLSD::emptyMap(), llsdcycle, llsdskylist, llsdwater);
}
LLSettingsSkyPtr_t LLSettingsVODay::getDefaultSky() const
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 4d99ee1386..f7df4286fe 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1826,116 +1826,6 @@ void renderUpdateType(LLDrawable* drawablep)
}
}
-void renderComplexityDisplay(LLDrawable* drawablep)
-{
- LLViewerObject* vobj = drawablep->getVObj();
- if (!vobj)
- {
- return;
- }
-
- LLVOVolume *voVol = dynamic_cast<LLVOVolume*>(vobj);
-
- if (!voVol)
- {
- return;
- }
-
- if (!voVol->isRoot())
- {
- return;
- }
-
- LLVOVolume::texture_cost_t textures;
- F32 cost = (F32) voVol->getRenderCost(textures);
-
- // add any child volumes
- LLViewerObject::const_child_list_t children = voVol->getChildren();
- for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
- {
- const LLViewerObject *child = *iter;
- const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child);
- if (child_volume)
- {
- cost += child_volume->getRenderCost(textures);
- }
- }
-
- // add texture cost
- for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
- {
- // add the cost of each individual texture in the linkset
- cost += iter->second;
- }
-
- F32 cost_max = (F32) LLVOVolume::getRenderComplexityMax();
-
-
-
- // allow user to set a static color scale
- if (gSavedSettings.getS32("RenderComplexityStaticMax") > 0)
- {
- cost_max = gSavedSettings.getS32("RenderComplexityStaticMax");
- }
-
- F32 cost_ratio = cost / cost_max;
-
- // cap cost ratio at 1.0f in case cost_max is at a low threshold
- cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio;
-
- LLGLEnable blend(GL_BLEND);
-
- LLColor4 color;
- const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin");
- const LLColor4 color_mid = gSavedSettings.getColor4("RenderComplexityColorMid");
- const LLColor4 color_max = gSavedSettings.getColor4("RenderComplexityColorMax");
-
- if (cost_ratio < 0.5f)
- {
- color = color_min * (1 - cost_ratio * 2) + color_mid * (cost_ratio * 2);
- }
- else
- {
- color = color_mid * (1 - (cost_ratio - 0.5) * 2) + color_max * ((cost_ratio - 0.5) * 2);
- }
-
- LLSD color_val = color.getValue();
-
- // don't highlight objects below the threshold
- if (cost > gSavedSettings.getS32("RenderComplexityThreshold"))
- {
- glColor4f(color[0],color[1],color[2],0.5f);
-
-
- S32 num_faces = drawablep->getNumFaces();
- if (num_faces)
- {
- for (S32 i = 0; i < num_faces; ++i)
- {
- pushVerts(drawablep->getFace(i));
- }
- }
- LLViewerObject::const_child_list_t children = voVol->getChildren();
- for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
- {
- const LLViewerObject *child = *iter;
- if (child)
- {
- num_faces = child->getNumFaces();
- if (num_faces)
- {
- for (S32 i = 0; i < num_faces; ++i)
- {
- pushVerts(child->mDrawable->getFace(i));
- }
- }
- }
- }
- }
-
- voVol->setDebugText(llformat("%4.0f", cost));
-}
-
void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
{
if (set_color)
@@ -3261,10 +3151,6 @@ public:
{
renderUpdateType(drawable);
}
- if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY))
- {
- renderComplexityDisplay(drawable);
- }
if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
renderTexelDensity(drawable);
@@ -3575,7 +3461,6 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_AGENT_TARGET |
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
- LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY |
LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
return;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 6bcee31b72..65fdd400bf 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -208,6 +208,7 @@
#include "llstacktrace.h"
#include "threadpool.h"
+#include "llperfstats.h"
#if LL_WINDOWS
@@ -1502,6 +1503,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
@@ -2346,6 +2349,8 @@ bool idle_startup()
LLUIUsage::instance().clear();
+ LLPerfStats::StatsRecorder::setAutotuneInit();
+
return TRUE;
}
@@ -3408,6 +3413,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/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp
index 01d799dcd5..4f47c465c4 100644
--- a/indra/newview/lltoolbarview.cpp
+++ b/indra/newview/lltoolbarview.cpp
@@ -44,6 +44,7 @@
#include "llagent.h" // HACK for destinations guide on startup
#include "llfloaterreg.h" // HACK for destinations guide on startup
#include "llviewercontrol.h" // HACK for destinations guide on startup
+#include "llinventorymodel.h" // HACK to disable starter avatars button for NUX
#include <boost/foreach.hpp>
@@ -319,6 +320,25 @@ bool LLToolBarView::loadToolbars(bool force_default)
}
}
}
+
+ // SL-18581: Don't show the starter avatar toolbar button for NUX users
+ LLViewerInventoryCategory* my_outfits_cat = gInventory.getCategory(gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
+ if (gAgent.isFirstLogin())
+ {
+ LL_WARNS() << "First login: checking for NUX user." << LL_ENDL;
+ if (my_outfits_cat != NULL && my_outfits_cat->getDescendentCount() > 0)
+ {
+ LL_WARNS() << "First login: My Outfits folder is not empty, removing the avatar picker button." << LL_ENDL;
+ for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
+ {
+ if (mToolbars[i])
+ {
+ mToolbars[i]->removeCommand(LLCommandId("avatar"));
+ }
+ }
+ }
+ }
+
mToolbarsLoaded = true;
return true;
}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 1b19ba33a3..6633951db3 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -2150,12 +2150,14 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
if (nodep)
{
uuid_vec_t material_ids;
+ gltf_materials_vec_t override_materials;
S32 num_faces = obj->getNumTEs();
for (S32 face = 0; face < num_faces; face++)
{
material_ids.push_back(obj->getRenderMaterialID(face));
+ override_materials.push_back(nullptr);
}
- nodep->saveGLTFMaterialIds(material_ids);
+ nodep->saveGLTFMaterials(material_ids, override_materials);
}
}
else
@@ -2169,6 +2171,7 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
&& nodep->mSavedGLTFMaterialIds.size() > face)
{
nodep->mSavedGLTFMaterialIds[face] = obj->getRenderMaterialID(face);
+ nodep->mSavedGLTFOverrideMaterials[face] = nullptr;
}
}
}
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index bbdae95b7f..faeebc33ee 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -74,6 +74,7 @@
#include "llspellcheck.h"
#include "llslurl.h"
#include "llstartup.h"
+#include "llperfstats.h"
// Third party library includes
#include <boost/algorithm/string.hpp>
@@ -247,8 +248,15 @@ static bool handleAnisotropicChanged(const LLSD& newvalue)
static bool handleVSyncChanged(const LLSD& newvalue)
{
+ LLPerfStats::tunables.vsyncEnabled = newvalue.asBoolean();
gViewerWindow->getWindow()->toggleVSync(newvalue.asBoolean());
+ if(newvalue.asBoolean() == true)
+ {
+ U32 current_target = gSavedSettings.getU32("TargetFPS");
+ gSavedSettings.setU32("TargetFPS", std::min((U32)gViewerWindow->getWindow()->getRefreshRate(), current_target));
+ }
+
return true;
}
@@ -585,6 +593,71 @@ 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");
+
+ U32 frame_rate_limit = gViewerWindow->getWindow()->getRefreshRate();
+ if(LLPerfStats::tunables.vsyncEnabled && (targetFPS > frame_rate_limit))
+ {
+ gSavedSettings.setU32("TargetFPS", std::min(frame_rate_limit, targetFPS));
+ }
+ else
+ {
+ LLPerfStats::tunables.userTargetFPS = targetFPS;
+ }
+}
+
+void handleAutoTuneLockChanged(const LLSD& newValue)
+{
+ const auto newval = gSavedSettings.getBOOL("AutoTuneLock");
+ LLPerfStats::tunables.userAutoTuneLock = newval;
+
+ gSavedSettings.setBOOL("AutoTuneFPS", 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 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)
@@ -618,142 +691,152 @@ 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, "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, "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, "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, "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, "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, "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, "RenderDeferredNoise", handleReleaseGLBufferChanged);
+ setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged);
+ setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged);
setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeLevel", handleReflectionProbeDetailChanged);
- setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged);
+ setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged);
setting_setup_signal_listener(gSavedSettings, "RenderReflectionsEnabled", handleReflectionProbeDetailChanged);
setting_setup_signal_listener(gSavedSettings, "RenderScreenSpaceReflections", handleReflectionProbeDetailChanged);
- 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, "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, "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, "RenderShadowDetail", handleSetShaderChanged);
+ setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged);
+ setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged);
+ 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, "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, "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 1730b02017..a2938eaefe 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -79,6 +79,7 @@
#include "llscenemonitor.h"
#include "llenvironment.h"
+#include "llperfstats.h"
extern LLPointer<LLViewerTexture> gStartTexture;
extern bool gShiftFrame;
@@ -243,6 +244,7 @@ void display_stats()
// Paint the display!
void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
+ LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_DISPLAY); // render time capture - This is the main stat for overall rendering.
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render");
if (gWindowResized)
@@ -1090,7 +1092,8 @@ void display_cube_face()
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();
@@ -1289,7 +1292,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);
LL_PROFILE_GPU_ZONE("ui");
LLGLState::checkStates();
@@ -1368,6 +1372,7 @@ void render_ui(F32 zoom_factor, int subfield)
void swap()
{
+ LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_SWAP ); // render time capture - Swap buffer time - can signify excessive data transfer to/from GPU
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Swap");
LL_PROFILE_GPU_ZONE("swap");
if (gDisplaySwapBuffers)
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 14d5a7c276..ca87ff0092 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"
@@ -408,6 +410,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 be2a1da968..5ce8f4023d 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;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 25efe189cb..d22ffc784a 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3281,6 +3281,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/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 100c73377f..77b4804076 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -369,7 +369,7 @@ LLViewerObject::~LLViewerObject()
}
// Delete memory associated with extra parameters.
- std::map<U16, ExtraParameter*>::iterator iter;
+ std::unordered_map<U16, ExtraParameter*>::iterator iter;
for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
{
if(iter->second != NULL)
@@ -1555,7 +1555,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
unpackParticleSource(block_num, owner_id);
// Mark all extra parameters not used
- std::map<U16, ExtraParameter*>::iterator iter;
+ std::unordered_map<U16, ExtraParameter*>::iterator iter;
for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
{
iter->second->in_use = FALSE;
@@ -1947,7 +1947,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
// Mark all extra parameters not used
- std::map<U16, ExtraParameter*>::iterator iter;
+ std::unordered_map<U16, ExtraParameter*>::iterator iter;
for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
{
iter->second->in_use = FALSE;
@@ -3965,6 +3965,7 @@ U32 LLViewerObject::recursiveGetTriangleCount(S32* vcount) const
// prim's scale. Should revisit at some point.
F32 LLViewerObject::recursiveGetScaledSurfaceArea() const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
F32 area = 0.f;
const LLDrawable* drawable = mDrawable;
if (drawable)
@@ -5689,7 +5690,7 @@ S32 LLViewerObject::countInventoryContents(LLAssetType::EType type)
return count;
}
-void LLViewerObject::setDebugText(const std::string &utf8text)
+void LLViewerObject::setDebugText(const std::string &utf8text, const LLColor4& color)
{
if (utf8text.empty() && !mText)
{
@@ -5700,7 +5701,7 @@ void LLViewerObject::setDebugText(const std::string &utf8text)
{
initHudText();
}
- mText->setColor(LLColor4::white);
+ mText->setColor(color);
mText->setString(utf8text);
mText->setZCompare(FALSE);
mText->setDoFade(FALSE);
@@ -6241,7 +6242,8 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const
{
- std::map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VIEWER;
+ std::unordered_map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type);
if (itor != mExtraParameterList.end())
{
return itor->second;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index e647fdd045..a18d07d970 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -28,6 +28,7 @@
#define LL_LLVIEWEROBJECT_H
#include <map>
+#include <unordered_map>
#include "llassetstorage.h"
//#include "llhudicon.h"
@@ -122,7 +123,7 @@ protected:
BOOL in_use;
LLNetworkData *data;
};
- std::map<U16, ExtraParameter*> mExtraParameterList;
+ std::unordered_map<U16, ExtraParameter*> mExtraParameterList;
public:
typedef std::list<LLPointer<LLViewerObject> > child_list_t;
@@ -441,7 +442,7 @@ public:
void sendMaterialUpdate() const;
- void setDebugText(const std::string &utf8text);
+ void setDebugText(const std::string &utf8text, const LLColor4& color = LLColor4::white);
void appendDebugText(const std::string &utf8text);
void initHudText();
void restoreHudText();
@@ -941,6 +942,10 @@ public:
// reflection probe state
bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager
LLPointer<LLReflectionMap> mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed
+
+ // the amount of GPU time (in ms) it took to render this object according to LLPipeline::profileAvatar
+ // -1.f if no profile data available
+ F32 mGPURenderTime = -1.f;
};
///////////////////
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index e5265f1dcd..449fd4ba43 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()->isTooSlow())
{
upd = FALSE;
}
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 63cc7ba623..4ceef07e72 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -188,6 +188,8 @@ LLGLSLShader gDeferredPostProgram;
LLGLSLShader gDeferredCoFProgram;
LLGLSLShader gDeferredDoFCombineProgram;
LLGLSLShader gDeferredPostGammaCorrectProgram;
+LLGLSLShader gNoPostGammaCorrectProgram;
+LLGLSLShader gLegacyPostGammaCorrectProgram;
LLGLSLShader gExposureProgram;
LLGLSLShader gLuminanceProgram;
LLGLSLShader gFXAAProgram;
@@ -295,6 +297,8 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gHUDPBRAlphaProgram);
mShaderList.push_back(&gDeferredSkinnedPBRAlphaProgram);
mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma
+ mShaderList.push_back(&gNoPostGammaCorrectProgram);
+ mShaderList.push_back(&gLegacyPostGammaCorrectProgram);
}
@@ -1010,6 +1014,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gExposureProgram.unload();
gLuminanceProgram.unload();
gDeferredPostGammaCorrectProgram.unload();
+ gNoPostGammaCorrectProgram.unload();
+ gLegacyPostGammaCorrectProgram.unload();
gFXAAProgram.unload();
gDeferredWLSkyProgram.unload();
gDeferredWLCloudProgram.unload();
@@ -2338,11 +2344,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredShadowGLTFAlphaMaskProgram.mName = "Deferred GLTF Shadow Alpha Mask Shader";
gDeferredShadowGLTFAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.clear();
- gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER));
- gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
+ gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/pbrShadowAlphaMaskV.glsl", GL_VERTEX_SHADER));
+ gDeferredShadowGLTFAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/pbrShadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
gDeferredShadowGLTFAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredShadowGLTFAlphaMaskProgram.clearPermutations();
- gDeferredShadowGLTFAlphaMaskProgram.addPermutation("GLTF", "1");
success = make_rigged_variant(gDeferredShadowGLTFAlphaMaskProgram, gDeferredSkinnedShadowGLTFAlphaMaskProgram);
success = success && gDeferredShadowGLTFAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
@@ -2537,6 +2542,37 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL);
llassert(success);
}
+
+ if (success)
+ {
+ gNoPostGammaCorrectProgram.mName = "No Post Gamma Correction Post Process";
+ gNoPostGammaCorrectProgram.mFeatures.hasSrgb = true;
+ gNoPostGammaCorrectProgram.mFeatures.isDeferred = true;
+ gNoPostGammaCorrectProgram.mShaderFiles.clear();
+ gNoPostGammaCorrectProgram.clearPermutations();
+ gNoPostGammaCorrectProgram.addPermutation("NO_POST", "1");
+ gNoPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gNoPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
+ gNoPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = gNoPostGammaCorrectProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
+ if (success)
+ {
+ gLegacyPostGammaCorrectProgram.mName = "Legacy Gamma Correction Post Process";
+ gLegacyPostGammaCorrectProgram.mFeatures.hasSrgb = true;
+ gLegacyPostGammaCorrectProgram.mFeatures.isDeferred = true;
+ gLegacyPostGammaCorrectProgram.mShaderFiles.clear();
+ gLegacyPostGammaCorrectProgram.clearPermutations();
+ gLegacyPostGammaCorrectProgram.addPermutation("LEGACY_GAMMA", "1");
+ gLegacyPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
+ gLegacyPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
+ gLegacyPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = gLegacyPostGammaCorrectProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
if (success && gGLManager.mGLVersion > 3.9f)
{
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 129802aca5..492e60b840 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -235,6 +235,8 @@ extern LLGLSLShader gDeferredDoFCombineProgram;
extern LLGLSLShader gFXAAProgram;
extern LLGLSLShader gDeferredPostNoDoFProgram;
extern LLGLSLShader gDeferredPostGammaCorrectProgram;
+extern LLGLSLShader gNoPostGammaCorrectProgram;
+extern LLGLSLShader gLegacyPostGammaCorrectProgram;
extern LLGLSLShader gExposureProgram;
extern LLGLSLShader gLuminanceProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 986319f26d..37999e58ff 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"
@@ -254,6 +255,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()
@@ -452,6 +460,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::us_to_raw(LLVOAvatar::getTotalGPURenderTime());
+ // 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();
+ }
+ }
}
/*
@@ -551,6 +642,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;
@@ -737,12 +829,11 @@ void send_viewer_stats(bool include_preferences)
LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL;
- if (debugLoggingEnabled("LogViewerStatsPacket"))
- {
- std::string filename("viewer_stats_packet.xml");
- llofstream of(filename.c_str());
- LLSDSerialize::toPrettyXML(body,of);
- }
+ LL_DEBUGS("LogViewerStatsPacket");
+ std::string filename("viewer_stats_packet.xml");
+ llofstream of(filename.c_str());
+ LLSDSerialize::toPrettyXML(body,of);
+ LL_ENDL;
// The session ID token must never appear in logs
body["session_id"] = gAgentSessionID;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 5adb3f9ede..af65588709 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;
@@ -205,6 +207,8 @@ const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024;
const F32 MAX_TEXTURE_WAIT_TIME_SEC = 60;
+const S32 MIN_NONTUNED_AVS = 5;
+
enum ERenderName
{
RENDER_NAME_NEVER,
@@ -616,6 +620,8 @@ F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
F32 LLVOAvatar::sGreyTime = 0.f;
F32 LLVOAvatar::sGreyUpdateTime = 0.f;
LLPointer<LLViewerTexture> LLVOAvatar::sCloudTexture = NULL;
+std::vector<LLUUID> LLVOAvatar::sAVsIgnoringARTLimit;
+S32 LLVOAvatar::sAvatarsNearby = 0;
//-----------------------------------------------------------------------------
// Helper functions
@@ -814,6 +820,14 @@ LLVOAvatar::~LLVOAvatar()
debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding");
}
+ if(mTuned)
+ {
+ LLPerfStats::tunedAvatars--;
+ mTuned = false;
+ }
+ sAVsIgnoringARTLimit.erase(std::remove(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID), sAVsIgnoringARTLimit.end());
+
+
logPendingPhases();
LL_DEBUGS("Avatar") << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL;
@@ -1434,7 +1448,7 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
continue;
}
}
- if (vol && vol->isRiggedMesh())
+ if (vol && vol->isRiggedMeshFast())
{
continue;
}
@@ -2547,11 +2561,17 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL;
return;
}
+ // record time and refresh "tooSlow" status
+ 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())
{
+ if (!mIsControlAvatar)
+ {
+ idleUpdateNameTag( mLastRootPos );
+ }
return;
}
@@ -2676,6 +2696,10 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
if ((LLFrameTimer::getFrameCount() + mID.mData[0]) % compl_upd_freq == 0)
{
+ // DEPRECATED
+ // replace with LLPipeline::profileAvatar?
+ // Avatar profile takes ~ 0.5ms while idleUpdateRenderComplexity takes ~5ms
+ // (both are unacceptably costly)
idleUpdateRenderComplexity();
}
idleUpdateDebugInfo();
@@ -3131,7 +3155,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() && !isTooSlow())
{
setParticleSource(particle_parameters, getID());
}
@@ -3216,11 +3240,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.
@@ -3715,7 +3737,7 @@ bool LLVOAvatar::isVisuallyMuted()
}
else
{
- muted = isTooComplex();
+ muted = isTooComplex() || isTooSlow();
}
}
@@ -8275,6 +8297,86 @@ bool LLVOAvatar::isTooComplex() const
return too_complex;
}
+bool LLVOAvatar::isTooSlow() const
+{
+ static LLCachedControl<bool> always_render_friends(gSavedSettings, "AlwaysRenderFriends");
+ bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends);
+
+ if (render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER)
+ {
+ return false;
+ }
+ return mTooSlow;
+}
+
+// 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.
+
+ // get max render time in ms
+ F32 max_art_ms = (F32) (LLPerfStats::renderAvatarMaxART_ns / 1000000.0);
+
+ bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
+
+ bool ignore_tune = false;
+ if (autotune && sAVsIgnoringARTLimit.size() > 0)
+ {
+ auto it = std::find(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID);
+ if (it != sAVsIgnoringARTLimit.end())
+ {
+ S32 index = it - sAVsIgnoringARTLimit.begin();
+ ignore_tune = (index < (MIN_NONTUNED_AVS - sAvatarsNearby + 1 + LLPerfStats::tunedAvatars));
+ }
+ }
+
+ bool exceeds_max_ART =
+ ((LLPerfStats::renderAvatarMaxART_ns > 0) &&
+ (mGPURenderTime >= max_art_ms)); // NOTE: don't use getGPURenderTime accessor here to avoid "isTooSlow" feedback loop
+
+ if (exceeds_max_ART && !ignore_tune)
+ {
+ 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 = getGPURenderTime()*2.f >= max_art_ms; // NOTE: assumes shadow rendering doubles render time
+ }
+ }
+ }
+ else
+ {
+ mTooSlow = false;
+ mTooSlowWithoutShadows = false;
+
+ if (ignore_tune)
+ {
+ return;
+ }
+ }
+ if(mTooSlow && !mTuned)
+ {
+ LLPerfStats::tunedAvatars++; // increment the number of avatars that have been tweaked.
+ mTuned = true;
+ }
+ else if(!mTooSlow && mTuned)
+ {
+ LLPerfStats::tunedAvatars--;
+ mTuned = false;
+ }
+}
+
//-----------------------------------------------------------------------------
// findMotion()
//-----------------------------------------------------------------------------
@@ -10536,6 +10638,64 @@ void LLVOAvatar::idleUpdateRenderComplexity()
// Render Complexity
calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed
+
+ bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
+ if (autotune && !isDead())
+ {
+ static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+ F32 radius = render_far_clip * render_far_clip;
+
+ bool is_nearby = true;
+ if ((dist_vec_squared(getPositionGlobal(), gAgent.getPositionGlobal()) > radius) &&
+ (dist_vec_squared(getPositionGlobal(), gAgentCamera.getCameraPositionGlobal()) > radius))
+ {
+ is_nearby = false;
+ }
+
+ if (is_nearby && (sAVsIgnoringARTLimit.size() < MIN_NONTUNED_AVS))
+ {
+ if (std::count(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID) == 0)
+ {
+ sAVsIgnoringARTLimit.push_back(mID);
+ }
+ }
+ else if (!is_nearby)
+ {
+ sAVsIgnoringARTLimit.erase(std::remove(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID),
+ sAVsIgnoringARTLimit.end());
+ }
+ updateNearbyAvatarCount();
+ }
+}
+
+void LLVOAvatar::updateNearbyAvatarCount()
+{
+ static LLFrameTimer agent_update_timer;
+
+ if (agent_update_timer.getElapsedTimeF32() > 1.0f)
+ {
+ S32 avs_nearby = 0;
+ static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+ 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;
+ }
+ avs_nearby++;
+ }
+ char_iter++;
+ }
+ sAvatarsNearby = avs_nearby;
+ agent_update_timer.reset();
+ }
}
void LLVOAvatar::idleUpdateDebugInfo()
@@ -10626,6 +10786,7 @@ void LLVOAvatar::updateVisualComplexity()
mVisualComplexityStale = true;
}
+
// Account for the complexity of a single top-level object associated
// with an avatar. This will be either an attached object or an animated
// object.
@@ -10634,137 +10795,149 @@ 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)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
if (attached_object && !attached_object->isHUDAttachment())
- {
+ {
mAttachmentVisibleTriangleCount += attached_object->recursiveGetTriangleCount();
mAttachmentEstTriangleCount += attached_object->recursiveGetEstTrianglesMax();
mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea();
- textures.clear();
- const LLDrawable* drawable = attached_object->mDrawable;
- if (drawable)
- {
- const LLVOVolume* volume = drawable->getVOVolume();
- if (volume)
- {
- F32 attachment_total_cost = 0;
- F32 attachment_volume_cost = 0;
- F32 attachment_texture_cost = 0;
- F32 attachment_children_cost = 0;
+ textures.clear();
+ const LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
+ {
+ const LLVOVolume* volume = drawable->getVOVolume();
+ if (volume)
+ {
+ F32 attachment_total_cost = 0;
+ F32 attachment_volume_cost = 0;
+ F32 attachment_texture_cost = 0;
+ F32 attachment_children_cost = 0;
const F32 animated_object_attachment_surcharge = 1000;
- if (attached_object->isAnimatedObject())
+ if (volume->isAnimatedObjectFast())
{
attachment_volume_cost += animated_object_attachment_surcharge;
}
- attachment_volume_cost += volume->getRenderCost(textures);
+ attachment_volume_cost += volume->getRenderCost(textures);
- const_child_list_t children = volume->getChildren();
- for (const_child_list_t::const_iterator child_iter = children.begin();
- child_iter != children.end();
- ++child_iter)
- {
- LLViewerObject* child_obj = *child_iter;
- LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
- if (child)
- {
- attachment_children_cost += child->getRenderCost(textures);
- }
- }
+ const_child_list_t children = volume->getChildren();
+ for (const_child_list_t::const_iterator child_iter = children.begin();
+ child_iter != children.end();
+ ++child_iter)
+ {
+ LLViewerObject* child_obj = *child_iter;
+ LLVOVolume* child = dynamic_cast<LLVOVolume*>(child_obj);
+ if (child)
+ {
+ attachment_children_cost += child->getRenderCost(textures);
+ }
+ }
- for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
- volume_texture != textures.end();
- ++volume_texture)
- {
- // add the cost of each individual texture in the linkset
- attachment_texture_cost += volume_texture->second;
- }
- attachment_total_cost = attachment_volume_cost + attachment_texture_cost + attachment_children_cost;
- LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID()
- << " total: " << attachment_total_cost
- << ", volume: " << attachment_volume_cost
- << ", " << textures.size()
- << " textures: " << attachment_texture_cost
- << ", " << volume->numChildren()
- << " children: " << attachment_children_cost
- << 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()
- && attached_object
- && attached_object->isHUDAttachment()
- && !attached_object->isTempAttachment()
- && attached_object->mDrawable)
+ for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
+ volume_texture != textures.end();
+ ++volume_texture)
{
- textures.clear();
- BOOL is_rigged_mesh = attached_object->isRiggedMesh();
+ // add the cost of each individual texture in the linkset
+ attachment_texture_cost += LLVOVolume::getTextureCost(*volume_texture);
+ }
+ attachment_total_cost = attachment_volume_cost + attachment_texture_cost + attachment_children_cost;
+ LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID()
+ << " total: " << attachment_total_cost
+ << ", volume: " << attachment_volume_cost
+ << ", " << textures.size()
+ << " textures: " << attachment_texture_cost
+ << ", " << volume->numChildren()
+ << " children: " << attachment_children_cost
+ << 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);
+ }
+ }
+ }
+ }
+ if (isSelf()
+ && attached_object
+ && attached_object->isHUDAttachment()
+ && !attached_object->isTempAttachment()
+ && attached_object->mDrawable)
+ {
+ textures.clear();
mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea();
- const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
- if (volume)
- {
- LLHUDComplexity hud_object_complexity;
- hud_object_complexity.objectName = attached_object->getAttachmentItemName();
- hud_object_complexity.objectId = attached_object->getAttachmentItemID();
- std::string joint_name;
- gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name);
- hud_object_complexity.jointName = joint_name;
- // get cost and individual textures
- hud_object_complexity.objectsCost += volume->getRenderCost(textures);
- hud_object_complexity.objectsCount++;
-
- LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); ++iter)
- {
- LLViewerObject* childp = *iter;
- is_rigged_mesh |= childp->isRiggedMesh();
- const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
- if (chld_volume)
- {
- // get cost and individual textures
- hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures);
- hud_object_complexity.objectsCount++;
- }
- }
- if (is_rigged_mesh && !attached_object->mRiggedAttachedWarned)
- {
- LLSD args;
- LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
- args["NAME"] = itemp ? itemp->getName() : LLTrans::getString("Unknown");
- args["POINT"] = LLTrans::getString(getTargetAttachmentPoint(attached_object)->getName());
- LLNotificationsUtil::add("RiggedMeshAttachedToHUD", args);
+ const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
+ if (volume)
+ {
+ BOOL is_rigged_mesh = volume->isRiggedMeshFast();
+ LLHUDComplexity hud_object_complexity;
+ hud_object_complexity.objectName = attached_object->getAttachmentItemName();
+ hud_object_complexity.objectId = attached_object->getAttachmentItemID();
+ std::string joint_name;
+ gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name);
+ hud_object_complexity.jointName = joint_name;
+ // get cost and individual textures
+ hud_object_complexity.objectsCost += volume->getRenderCost(textures);
+ hud_object_complexity.objectsCount++;
+
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
+ if (chld_volume)
+ {
+ is_rigged_mesh = is_rigged_mesh || chld_volume->isRiggedMeshFast();
+ // get cost and individual textures
+ hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures);
+ hud_object_complexity.objectsCount++;
+ }
+ }
+ if (is_rigged_mesh && !attached_object->mRiggedAttachedWarned)
+ {
+ LLSD args;
+ LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
+ args["NAME"] = itemp ? itemp->getName() : LLTrans::getString("Unknown");
+ args["POINT"] = LLTrans::getString(getTargetAttachmentPoint(attached_object)->getName());
+ LLNotificationsUtil::add("RiggedMeshAttachedToHUD", args);
- attached_object->mRiggedAttachedWarned = true;
- }
+ attached_object->mRiggedAttachedWarned = true;
+ }
- hud_object_complexity.texturesCount += textures.size();
+ hud_object_complexity.texturesCount += textures.size();
- for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
- volume_texture != textures.end();
- ++volume_texture)
- {
- // add the cost of each individual texture (ignores duplicates)
- hud_object_complexity.texturesCost += volume_texture->second;
- LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first);
- if (tex)
- {
- // Note: Texture memory might be incorect since texture might be still loading.
- hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory();
- if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE)
- {
- hud_object_complexity.largeTexturesCount++;
- }
- }
- }
- hud_complexity_list.push_back(hud_object_complexity);
+ for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
+ volume_texture != textures.end();
+ ++volume_texture)
+ {
+ // add the cost of each individual texture (ignores duplicates)
+ hud_object_complexity.texturesCost += LLVOVolume::getTextureCost(*volume_texture);
+ const LLViewerTexture* img = *volume_texture;
+ if (img->getType() == LLViewerTexture::FETCHED_TEXTURE)
+ {
+ LLViewerFetchedTexture* tex = (LLViewerFetchedTexture*)img;
+ // Note: Texture memory might be incorect since texture might be still loading.
+ hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory();
+ if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE)
+ {
+ hud_object_complexity.largeTexturesCount++;
}
}
+ }
+ hud_complexity_list.push_back(hud_object_complexity);
+ }
+ }
}
// Calculations for mVisualComplexity value
@@ -10776,19 +10949,22 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
* everyone. If you have suggested improvements, submit them to
* the official viewer for consideration.
*****************************************************************/
- static const U32 COMPLEXITY_BODY_PART_COST = 200;
- static LLCachedControl<F32> max_complexity_setting(gSavedSettings,"MaxAttachmentComplexity");
- F32 max_attachment_complexity = max_complexity_setting;
- max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY);
-
- // Diagnostic list of all textures on our avatar
- static std::set<LLUUID> all_textures;
-
if (mVisualComplexityStale)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ static const U32 COMPLEXITY_BODY_PART_COST = 200;
+ static LLCachedControl<F32> max_complexity_setting(gSavedSettings, "MaxAttachmentComplexity");
+ F32 max_attachment_complexity = max_complexity_setting;
+ max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY);
+
+ // Diagnostic list of all textures on our avatar
+ static std::unordered_set<const LLViewerTexture*> all_textures;
+
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++)
{
@@ -10832,7 +11008,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);
}
}
@@ -10848,45 +11024,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
{
LLViewerObject* attached_object = attachment_iter->get();
accountRenderComplexityForObject(attached_object, max_attachment_complexity,
- textures, cost, hud_complexity_list);
- }
- }
-
- // Diagnostic output to identify all avatar-related textures.
- // Does not affect rendering cost calculation.
- if (isSelf() && debugLoggingEnabled("ARCdetail"))
- {
- // print any attachment textures we didn't already know about.
- for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
- {
- LLUUID image_id = it->first;
- if( ! (image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
- && (all_textures.find(image_id) == all_textures.end()))
- {
- // attachment texture not previously seen.
- LL_DEBUGS("ARCdetail") << "attachment_texture: " << image_id.asString() << LL_ENDL;
- all_textures.insert(image_id);
- }
- }
-
- // print any avatar textures we didn't already know about
- for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin();
- iter != LLAvatarAppearance::getDictionary()->getTextures().end();
- ++iter)
- {
- const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
- // TODO: MULTI-WEARABLE: handle multiple textures for self
- const LLViewerTexture* te_image = getImage(iter->first,0);
- if (!te_image)
- continue;
- LLUUID image_id = te_image->getID();
- if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
- continue;
- if (all_textures.find(image_id) == all_textures.end())
- {
- LL_DEBUGS("ARCdetail") << "local_texture: " << texture_dict->mName << ": " << image_id << LL_ENDL;
- all_textures.insert(image_id);
- }
+ textures, cost, hud_complexity_list, object_complexity_list);
}
}
@@ -10913,10 +11051,25 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
{
// Avatar complexity
LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
-
+ LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list);
// HUD complexity
LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
}
+
+ //schedule an update to ART next frame if needed
+ if (LLPerfStats::tunables.userAutoTuneEnabled &&
+ LLPerfStats::tunables.userFPSTuningStrategy != LLPerfStats::TUNE_SCENE_ONLY &&
+ !isVisuallyMuted())
+ {
+ LLUUID id = getID(); // <== use id to make sure this avatar didn't get deleted between frames
+ LL::WorkQueue::getInstance("mainloop")->post([this, id]()
+ {
+ if (gObjectList.findObject(id) != nullptr)
+ {
+ gPipeline.profileAvatar(this);
+ }
+ });
+ }
}
}
@@ -11088,7 +11241,7 @@ LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const
{ // Always want to see this AV as an impostor
result = AOA_JELLYDOLL;
}
- else if (isTooComplex())
+ else if (isTooComplex() || isTooSlow())
{
result = AOA_JELLYDOLL;
}
@@ -11115,7 +11268,7 @@ void LLVOAvatar::calcMutedAVColor()
new_color = LLColor4::grey4;
change_msg = " blocked: color is grey4";
}
- else if (!isTooComplex())
+ else if (!isTooComplex() && !isTooSlow())
{
new_color = LLColor4::white;
change_msg = " simple imposter ";
@@ -11251,3 +11404,110 @@ BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type,
// non-self avatars don't have wearables
return FALSE;
}
+
+void LLVOAvatar::placeProfileQuery()
+{
+ if (mGPUTimerQuery == 0)
+ {
+ glGenQueries(1, &mGPUTimerQuery);
+ }
+
+ glBeginQuery(GL_TIME_ELAPSED, mGPUTimerQuery);
+}
+
+void LLVOAvatar::readProfileQuery(S32 retries)
+{
+ if (!mGPUProfilePending)
+ {
+ glEndQuery(GL_TIME_ELAPSED);
+ mGPUProfilePending = true;
+ }
+
+ GLuint64 result = 0;
+ glGetQueryObjectui64v(mGPUTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result);
+
+ if (result == GL_TRUE || --retries <= 0)
+ { // query available, readback result
+ GLuint64 time_elapsed = 0;
+ glGetQueryObjectui64v(mGPUTimerQuery, GL_QUERY_RESULT, &time_elapsed);
+ mGPURenderTime = time_elapsed / 1000000.f;
+ mGPUProfilePending = false;
+
+ setDebugText(llformat("%d", (S32)(mGPURenderTime * 1000.f)));
+
+ }
+ else
+ { // wait until next frame
+ LLUUID id = getID();
+
+ LL::WorkQueue::getInstance("mainloop")->post([id, retries] {
+ LLVOAvatar* avatar = (LLVOAvatar*) gObjectList.findObject(id);
+ avatar->readProfileQuery(retries);
+ });
+ }
+}
+
+
+F32 LLVOAvatar::getGPURenderTime()
+{
+ return isVisuallyMuted() ? 0.f : mGPURenderTime;
+}
+
+// static
+F32 LLVOAvatar::getTotalGPURenderTime()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ F32 ret = 0.f;
+
+ for (LLCharacter* iter : LLCharacter::sInstances)
+ {
+ LLVOAvatar* inst = (LLVOAvatar*) iter;
+ ret += inst->getGPURenderTime();
+ }
+
+ return ret;
+}
+
+F32 LLVOAvatar::getMaxGPURenderTime()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ F32 ret = 0.f;
+
+ for (LLCharacter* iter : LLCharacter::sInstances)
+ {
+ LLVOAvatar* inst = (LLVOAvatar*)iter;
+ ret = llmax(inst->getGPURenderTime(), ret);
+ }
+
+ return ret;
+}
+
+F32 LLVOAvatar::getAverageGPURenderTime()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
+
+ F32 ret = 0.f;
+
+ S32 count = 0;
+
+ for (LLCharacter* iter : LLCharacter::sInstances)
+ {
+ LLVOAvatar* inst = (LLVOAvatar*)iter;
+ if (!inst->isTooSlow())
+ {
+ ret += inst->getGPURenderTime();
+ ++count;
+ }
+ }
+
+ if (count > 0)
+ {
+ ret /= count;
+ }
+
+ return ret;
+}
+
+
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 7cc3337243..e8604464ae 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -299,13 +299,39 @@ 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();
- U32 getVisualComplexity() { return mVisualComplexity; }; // Numbers calculated here by rendering AV
- F32 getAttachmentSurfaceArea() { return mAttachmentSurfaceArea; }; // estimated surface area of attachments
+ void placeProfileQuery();
+ void readProfileQuery(S32 retries);
+
+ // get the GPU time in ms of rendering this avatar including all attachments
+ // returns 0.f if this avatar has not been profiled using gPipeline.profileAvatar
+ // or the avatar is visually muted
+ F32 getGPURenderTime();
+
+ // get the total GPU render time in ms of all avatars that have been benched
+ static F32 getTotalGPURenderTime();
+
+ // get the max GPU render time in ms of all avatars that have been benched
+ static F32 getMaxGPURenderTime();
+
+ // get the average GPU render time in ms of all avatars that have been benched
+ static F32 getAverageGPURenderTime();
+
+ // get the CPU time in ms of rendering this avatar including all attachments
+ // return 0.f if this avatar has not been profiled using gPipeline.mProfileAvatar
+ F32 getCPURenderTime() { return mCPURenderTime; }
+
+
+ // avatar render cost
+ U32 getVisualComplexity() { return mVisualComplexity; };
+
+ // surface area calculation
+ F32 getAttachmentSurfaceArea() { return mAttachmentSurfaceArea; };
U32 getReportedVisualComplexity() { return mReportedVisualComplexity; }; // Numbers as reported by the SL server
void setReportedVisualComplexity(U32 value) { mReportedVisualComplexity = value; };
@@ -316,6 +342,8 @@ public:
void idleUpdateBelowWater();
+ static void updateNearbyAvatarCount();
+
//--------------------------------------------------------------------
// Static preferences (controlled by user settings/menus)
//--------------------------------------------------------------------
@@ -340,6 +368,9 @@ public:
static LLPointer<LLViewerTexture> sCloudTexture;
+ static std::vector<LLUUID> sAVsIgnoringARTLimit;
+ static S32 sAvatarsNearby;
+
//--------------------------------------------------------------------
// Region state
//--------------------------------------------------------------------
@@ -351,6 +382,16 @@ 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 isTooSlowWithoutShadows() const {return mTooSlowWithoutShadows;};
+ bool isTooSlow() const;
+
+ void updateTooSlow();
+
bool isTooComplex() const;
bool visualParamWeightsAreDefault();
virtual bool getIsCloud() const;
@@ -370,7 +411,7 @@ public:
void logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed);
void calcMutedAVColor();
-
+
protected:
LLViewerStats::PhaseMap& getPhases() { return mPhases; }
BOOL updateIsFullyLoaded();
@@ -391,6 +432,12 @@ private:
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
+ // variables to hold "slowness" status
+ bool mTooSlow{false};
+ bool mTooSlowWithoutShadows{false};
+
+ bool mTuned{false};
+
private:
LLViewerStats::PhaseMap mPhases;
@@ -495,6 +542,7 @@ public:
S32 mSpecialRenderMode; // special lighting
private:
+ friend class LLPipeline;
AvatarOverallAppearance mOverallAppearance;
F32 mAttachmentSurfaceArea; //estimated surface area of attachments
U32 mAttachmentVisibleTriangleCount;
@@ -507,7 +555,20 @@ private:
S32 mUpdatePeriod;
S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
+ // profile handle
+ U32 mGPUTimerQuery = 0;
+
+ // profile results
+
+ // GPU render time in ms
+ F32 mGPURenderTime = 0.f;
+ bool mGPUProfilePending = false;
+
+ // CPU render time in ms
+ F32 mCPURenderTime = 0.f;
+
// the isTooComplex method uses these mutable values to avoid recalculating too frequently
+ // DEPRECATED -- obsolete avatar render cost values
mutable U32 mVisualComplexity;
mutable bool mVisualComplexityStale;
U32 mReportedVisualComplexity; // from other viewers through the simulator
@@ -623,7 +684,7 @@ private:
//--------------------------------------------------------------------
public:
virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLGLTexture::BOOST_AVATAR; }
- virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLGLTexture::BOOST_AVATAR_BAKED; }
+ virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLGLTexture::BOOST_AVATAR_BAKED_SELF; }
virtual S32 getTexImageSize() const;
/*virtual*/ S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); }
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index d8b82d3114..82dfb1ca2a 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1155,6 +1155,7 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id)
bool LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
if (!gInventory.getItem(inv_item_id))
{
name = "ATTACHMENT_MISSING_ITEM";
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index a73d149b10..aa60578cee 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1603,7 +1603,9 @@ BOOL LLVOVolume::updateLOD()
{
return FALSE;
}
-
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+
BOOL lod_changed = FALSE;
if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID()))
@@ -1617,16 +1619,6 @@ BOOL LLVOVolume::updateLOD()
if (lod_changed)
{
- if (debugLoggingEnabled("AnimatedObjectsLinkset"))
- {
- if (isAnimatedObject() && isRiggedMesh())
- {
- std::string vobj_name = llformat("Vol%p", this);
- F32 est_tris = getEstTrianglesMax();
- LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " updateLOD to " << getLOD() << ", tris " << est_tris << LL_ENDL;
- }
- }
-
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
mLODChanged = TRUE;
}
@@ -3198,7 +3190,13 @@ void LLVOVolume::setLightCutoff(F32 cutoff)
BOOL LLVOVolume::getIsLight() const
{
- return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT);
+ mIsLight = getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT);
+ return mIsLight;
+}
+
+bool LLVOVolume::getIsLightFast() const
+{
+ return mIsLight;
}
LLColor3 LLVOVolume::getLightSRGBBaseColor() const
@@ -3584,6 +3582,31 @@ BOOL LLVOVolume::hasLightTexture() const
return FALSE;
}
+bool LLVOVolume::isFlexibleFast() const
+{
+ return mVolumep && mVolumep->getParams().getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE;
+}
+
+bool LLVOVolume::isSculptedFast() const
+{
+ return mVolumep && mVolumep->getParams().isSculpt();
+}
+
+bool LLVOVolume::isMeshFast() const
+{
+ return mVolumep && mVolumep->getParams().isMeshSculpt();
+}
+
+bool LLVOVolume::isRiggedMeshFast() const
+{
+ return mSkinInfo.notNull();
+}
+
+bool LLVOVolume::isAnimatedObjectFast() const
+{
+ return mIsAnimatedObject;
+}
+
BOOL LLVOVolume::isVolumeGlobal() const
{
if (mVolumeImpl)
@@ -3744,8 +3767,8 @@ bool LLVOVolume::canBeAnimatedObject() const
bool LLVOVolume::isAnimatedObject() const
{
LLVOVolume *root_vol = (LLVOVolume*)getRootEdit();
- bool root_is_animated_flag = root_vol->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG;
- return root_is_animated_flag;
+ mIsAnimatedObject = root_vol->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG;
+ return mIsAnimatedObject;
}
// Called any time parenting changes for a volume. Update flags and
@@ -3932,12 +3955,41 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
return mDrawable->getWorldMatrix();
}
+//static
+S32 LLVOVolume::getTextureCost(const LLViewerTexture* img)
+{
+ static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested
+
+ S32 texture_cost = 0;
+ S8 type = img->getType();
+ if (type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
+ {
+ const LLViewerFetchedTexture* fetched_texturep = static_cast<const LLViewerFetchedTexture*>(img);
+ if (fetched_texturep
+ && fetched_texturep->getFTType() == FTT_LOCAL_FILE
+ && (img->getID() == IMG_ALPHA_GRAD_2D || img->getID() == IMG_ALPHA_GRAD)
+ )
+ {
+ // These two textures appear to switch between each other, but are of different sizes (4x256 and 256x256).
+ // Hardcode cost from larger one to not cause random complexity changes
+ texture_cost = 320;
+ }
+ }
+ if (texture_cost == 0)
+ {
+ texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f));
+ }
+
+ return texture_cost;
+}
+
// Returns a base cost and adds textures to passed in set.
// total cost is returned value + 5 * size of the resulting set.
// Cannot include cost of textures, as they may be re-used in linked
// children, and cost should only be increased for unique textures -Nyx
U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
/*****************************************************************
* This calculation should not be modified by third party viewers,
* since it is used to limit rendering and should be uniform for
@@ -3947,17 +3999,16 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
// Get access to params we'll need at various points.
// Skip if this is object doesn't have a volume (e.g. is an avatar).
- BOOL has_volume = (getVolume() != NULL);
- LLVolumeParams volume_params;
- LLPathParams path_params;
- LLProfileParams profile_params;
+ if (getVolume() == NULL)
+ {
+ return 0;
+ }
U32 num_triangles = 0;
// per-prim costs
static const U32 ARC_PARTICLE_COST = 1; // determined experimentally
static const U32 ARC_PARTICLE_MAX = 2048; // default values
- static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested
static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims
static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face
@@ -3992,45 +4043,41 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
const LLDrawable* drawablep = mDrawable;
U32 num_faces = drawablep->getNumFaces();
- if (has_volume)
- {
- volume_params = getVolume()->getParams();
- path_params = volume_params.getPathParams();
- profile_params = volume_params.getProfileParams();
+ const LLVolumeParams& volume_params = getVolume()->getParams();
- LLMeshCostData costs;
- if (getCostData(costs))
- {
- if (isAnimatedObject() && isRiggedMesh())
- {
- // Scaling here is to make animated object vs
- // non-animated object ARC proportional to the
- // corresponding calculations for streaming cost.
- num_triangles = (ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * costs.getEstTrisForStreamingCost())/0.06;
- }
- else
- {
- F32 radius = getScale().length()*0.5f;
- num_triangles = costs.getRadiusWeightedTris(radius);
- }
- }
+ LLMeshCostData costs;
+ if (getCostData(costs))
+ {
+ if (isAnimatedObjectFast() && isRiggedMeshFast())
+ {
+ // Scaling here is to make animated object vs
+ // non-animated object ARC proportional to the
+ // corresponding calculations for streaming cost.
+ num_triangles = (ANIMATED_OBJECT_COST_PER_KTRI * 0.001 * costs.getEstTrisForStreamingCost())/0.06;
+ }
+ else
+ {
+ F32 radius = getScale().length()*0.5f;
+ num_triangles = costs.getRadiusWeightedTris(radius);
+ }
}
+
if (num_triangles <= 0)
{
num_triangles = 4;
}
- if (isSculpted())
+ if (isSculptedFast())
{
- if (isMesh())
+ if (isMeshFast())
{
// base cost is dependent on mesh complexity
// note that 3 is the highest LOD as of the time of this coding.
S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD());
if ( size > 0)
{
- if (isRiggedMesh())
+ if (isRiggedMeshFast())
{
// weighted attachment - 1 point for every 3 bytes
weighted_mesh = 1;
@@ -4044,21 +4091,15 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
}
else
{
- const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID sculpt_id = sculpt_params->getSculptTexture();
- if (textures.find(sculpt_id) == textures.end())
+ LLViewerFetchedTexture* texture = mSculptTexture;
+ if (texture && textures.find(texture) == textures.end())
{
- LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id);
- if (texture)
- {
- S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f));
- textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost));
- }
+ textures.insert(texture);
}
}
}
- if (isFlexible())
+ if (isFlexibleFast())
{
flexi = 1;
}
@@ -4067,85 +4108,66 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
particles = 1;
}
- if (getIsLight())
+ if (getIsLightFast())
{
produces_light = 1;
}
- for (S32 i = 0; i < num_faces; ++i)
- {
- const LLFace* face = drawablep->getFace(i);
- if (!face) continue;
- const LLTextureEntry* te = face->getTextureEntry();
- const LLViewerTexture* img = face->getTexture();
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("ARC - face list");
+ for (S32 i = 0; i < num_faces; ++i)
+ {
+ const LLFace* face = drawablep->getFace(i);
+ if (!face) continue;
+ const LLTextureEntry* te = face->getTextureEntry();
+ const LLViewerTexture* img = face->getTexture();
- if (img)
- {
- if (textures.find(img->getID()) == textures.end())
- {
- S32 texture_cost = 0;
- S8 type = img->getType();
- if (type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
+ if (img)
+ {
+ textures.insert(img);
+ }
+
+ if (face->isInAlphaPool())
+ {
+ alpha = 1;
+ }
+ else if (img && img->getPrimaryFormat() == GL_ALPHA)
+ {
+ invisi = 1;
+ }
+ if (face->hasMedia())
+ {
+ media_faces++;
+ }
+
+ if (te)
+ {
+ if (te->getBumpmap())
{
- const LLViewerFetchedTexture* fetched_texturep = static_cast<const LLViewerFetchedTexture*>(img);
- if (fetched_texturep
- && fetched_texturep->getFTType() == FTT_LOCAL_FILE
- && (img->getID() == IMG_ALPHA_GRAD_2D || img->getID() == IMG_ALPHA_GRAD)
- )
- {
- // These two textures appear to switch between each other, but are of different sizes (4x256 and 256x256).
- // Hardcode cost from larger one to not cause random complexity changes
- texture_cost = 320;
- }
+ // bump is a multiplier, don't add per-face
+ bump = 1;
}
- if (texture_cost == 0)
+ if (te->getShiny())
{
- texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f));
+ // shiny is a multiplier, don't add per-face
+ shiny = 1;
}
- textures.insert(texture_cost_t::value_type(img->getID(), texture_cost));
- }
- }
-
- if (face->isInAlphaPool())
- {
- alpha = 1;
- }
- else if (img && img->getPrimaryFormat() == GL_ALPHA)
- {
- invisi = 1;
- }
- if (face->hasMedia())
- {
- media_faces++;
- }
-
- if (te)
- {
- if (te->getBumpmap())
- {
- // bump is a multiplier, don't add per-face
- bump = 1;
- }
- if (te->getShiny())
- {
- // shiny is a multiplier, don't add per-face
- shiny = 1;
- }
- if (te->getGlow() > 0.f)
- {
- // glow is a multiplier, don't add per-face
- glow = 1;
- }
- if (face->mTextureMatrix != NULL)
- {
- animtex = 1;
- }
- if (te->getTexGen())
- {
- planar = 1;
- }
- }
- }
+ if (te->getGlow() > 0.f)
+ {
+ // glow is a multiplier, don't add per-face
+ glow = 1;
+ }
+ if (face->mTextureMatrix != NULL)
+ {
+ animtex = 1;
+ }
+ if (te->getTexGen())
+ {
+ planar = 1;
+ }
+ }
+ }
+ }
// shame currently has the "base" cost of 1 point per 15 triangles, min 2.
shame = num_triangles * 5.f;
@@ -4224,7 +4246,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
// Streaming cost for animated objects includes a fixed cost
// per linkset. Add a corresponding charge here translated into
// triangles, but not weighted by any graphics properties.
- if (isAnimatedObject() && isRootEdit())
+ if (isAnimatedObjectFast() && isRootEdit())
{
shame += (ANIMATED_OBJECT_BASE_COST/0.06) * 5.0f;
}
@@ -4239,7 +4261,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
F32 LLVOVolume::getEstTrianglesMax() const
{
- if (isMesh() && getVolume())
+ if (isMeshFast() && getVolume())
{
return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID());
}
@@ -4248,7 +4270,7 @@ F32 LLVOVolume::getEstTrianglesMax() const
F32 LLVOVolume::getEstTrianglesStreamingCost() const
{
- if (isMesh() && getVolume())
+ if (isMeshFast() && getVolume())
{
return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID());
}
@@ -4263,7 +4285,7 @@ F32 LLVOVolume::getStreamingCost() const
LLMeshCostData costs;
if (getCostData(costs))
{
- if (isAnimatedObject() && isRootEdit())
+ if (isRootEdit() && isAnimatedObject())
{
// Root object of an animated object has this to account for skeleton overhead.
linkset_base_cost = ANIMATED_OBJECT_BASE_COST;
@@ -4293,7 +4315,9 @@ F32 LLVOVolume::getStreamingCost() const
// virtual
bool LLVOVolume::getCostData(LLMeshCostData& costs) const
{
- if (isMesh())
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+
+ if (isMeshFast())
{
return gMeshRepo.getCostData(getVolume()->getParams().getSculptID(), costs);
}
@@ -4303,11 +4327,11 @@ bool LLVOVolume::getCostData(LLMeshCostData& costs) const
S32 counts[4];
LLVolume::getLoDTriangleCounts(volume->getParams(), counts);
- LLSD header;
- header["lowest_lod"]["size"] = counts[0] * 10;
- header["low_lod"]["size"] = counts[1] * 10;
- header["medium_lod"]["size"] = counts[2] * 10;
- header["high_lod"]["size"] = counts[3] * 10;
+ LLMeshHeader header;
+ header.mLodSize[0] = counts[0] * 10;
+ header.mLodSize[1] = counts[1] * 10;
+ header.mLodSize[2] = counts[2] * 10;
+ header.mLodSize[3] = counts[3] * 10;
return gMeshRepo.getCostData(header, costs);
}
@@ -4532,16 +4556,6 @@ const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
void LLVOVolume::markForUpdate(BOOL priority)
{
- if (debugLoggingEnabled("AnimatedObjectsLinkset"))
- {
- if (isAnimatedObject() && isRiggedMesh())
- {
- std::string vobj_name = llformat("Vol%p", this);
- F32 est_tris = getEstTrianglesMax();
- LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " markForUpdate, tris " << est_tris << LL_ENDL;
- }
- }
-
if (mDrawable)
{
shrinkWrap();
@@ -5454,7 +5468,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
}
}
- if (type == LLRenderPass::PASS_ALPHA)
+ // if (type == LLRenderPass::PASS_ALPHA) // always populate the draw_info ptr
{ //for alpha sorting
facep->setDrawInfo(draw_info);
}
@@ -5826,7 +5840,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
const LLTextureEntry* te = facep->getTextureEntry();
LLViewerTexture* tex = facep->getTexture();
- if (te->getGlow() >= 1.f/255.f)
+ if (te->getGlow() > 0.f)
{
emissive = true;
}
@@ -5910,7 +5924,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial();
- if (gltf_mat != nullptr || (te->getMaterialParams().notNull() && !te->getMaterialID().isNull()))
+ if (gltf_mat != nullptr || (te->getMaterialParams().notNull()))
{
if (gltf_mat != nullptr)
{
@@ -6088,7 +6102,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
U32 buffer_count = 0;
- for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
+ for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
@@ -6097,16 +6111,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
LLVOVolume* vobj = drawablep->getVOVolume();
if (!vobj) continue;
-
- if (debugLoggingEnabled("AnimatedObjectsLinkset"))
- {
- if (vobj->isAnimatedObject() && vobj->isRiggedMesh())
- {
- std::string vobj_name = llformat("Vol%p", vobj);
- F32 est_tris = vobj->getEstTrianglesMax();
- LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL;
- }
- }
+
if (vobj->isNoLOD()) continue;
vobj->preRebuild();
@@ -6466,10 +6471,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
U32 indices_index = 0;
U16 index_offset = 0;
- while (face_iter < i)
+ while (face_iter < i)
{
//update face indices for new buffer
facep = *face_iter;
+
if (buffer.isNull())
{
// Bulk allocation failed
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 9cfd90a940..d509a7e2ab 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -34,8 +34,8 @@
#include "lllocalbitmaps.h"
#include "m3math.h" // LLMatrix3
#include "m4math.h" // LLMatrix4
-#include <map>
-#include <set>
+#include <unordered_map>
+#include <unordered_set>
class LLViewerTextureAnim;
@@ -146,7 +146,8 @@ public:
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
/*virtual*/ const LLMatrix4 getRenderMatrix() const override;
- typedef std::map<LLUUID, S32> texture_cost_t;
+ typedef std::unordered_set<const LLViewerTexture*> texture_cost_t;
+ static S32 getTextureCost(const LLViewerTexture* img);
U32 getRenderCost(texture_cost_t &textures) const;
/*virtual*/ F32 getEstTrianglesMax() const override;
/*virtual*/ F32 getEstTrianglesStreamingCost() const override;
@@ -267,6 +268,7 @@ public:
void setSpotLightParams(LLVector3 params);
BOOL getIsLight() const;
+ bool getIsLightFast() const;
// Get the light color in sRGB color space NOT scaled by intensity.
@@ -315,7 +317,15 @@ public:
virtual BOOL isRiggedMesh() const override;
virtual BOOL hasLightTexture() const override;
-
+ // fast variants above that use state that is filled in later
+ // not reliable early in the life of an object, but should be used after
+ // object is loaded
+ bool isFlexibleFast() const;
+ bool isSculptedFast() const;
+ bool isMeshFast() const;
+ bool isRiggedMeshFast() const;
+ bool isAnimatedObjectFast() const;
+
BOOL isVolumeGlobal() const;
BOOL canBeFlexible() const;
BOOL setIsFlexible(BOOL is_flexible);
@@ -461,6 +471,13 @@ private:
S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];
S32 mMDCImplCount;
+ // cached value of getIsLight to avoid redundant map lookups
+ // accessed by getIsLightFast
+ mutable bool mIsLight = false;
+
+ // cached value of getIsAnimatedObject to avoid redundant map lookups
+ // accessed by getIsAnimatedObjectFast
+ mutable bool mIsAnimatedObject = false;
bool mResetDebugText;
LLPointer<LLRiggedVolume> mRiggedVolume;
@@ -475,7 +492,6 @@ public:
static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient;
-
protected:
static S32 sNumLODChanges;
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 9fa3d18a40..0e0dbdc071 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"
@@ -1423,6 +1424,36 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi
}
}
+F32 LLWorld::getNearbyAvatarsAndMaxGPUTime(std::vector<LLCharacter*> &valid_nearby_avs)
+{
+ static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+ F32 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;
+ }
+
+ if (!avatar->isTooSlow())
+ {
+ gPipeline.profileAvatar(avatar);
+ }
+ nearby_max_complexity = llmax(nearby_max_complexity, avatar->getGPURenderTime());
+ 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 5dee8eea0f..f78cbcaa48 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;
@@ -171,6 +172,10 @@ public:
// or if the circuit to this simulator had been lost.
bool isRegionListed(const LLViewerRegion* region) const;
+ // profile nearby avatars using gPipeline.profileAvatar and update their render times
+ // return max GPU time
+ F32 getNearbyAvatarsAndMaxGPUTime(std::vector<LLCharacter*> &valid_nearby_avs);
+
private:
void clearHoleWaterObjects();
void clearEdgeWaterObjects();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 283be64af4..327a51de85 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
@@ -127,6 +128,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;
@@ -200,6 +202,7 @@ LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize");
const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
+const F32 ALPHA_BLEND_CUTOFF = 0.598f;
const F32 DEFERRED_LIGHT_FALLOFF = 0.5f;
const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
@@ -486,6 +489,7 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("RenderResolutionDivisor");
connectRefreshCachedSettingsSafe("RenderUIBuffer");
connectRefreshCachedSettingsSafe("RenderShadowDetail");
+ connectRefreshCachedSettingsSafe("RenderShadowSplits");
connectRefreshCachedSettingsSafe("RenderDeferredSSAO");
connectRefreshCachedSettingsSafe("RenderShadowResolutionScale");
connectRefreshCachedSettingsSafe("RenderLocalLights");
@@ -559,7 +563,6 @@ void LLPipeline::init()
LLPipeline::~LLPipeline()
{
-
}
void LLPipeline::cleanup()
@@ -971,10 +974,11 @@ void LLPipeline::refreshCachedSettings()
WindLightUseAtmosShaders = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders");
RenderDeferred = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred");
RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");
- RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
+ RenderFSAASamples = LLFeatureManager::getInstance()->isFeatureAvailable("RenderFSAASamples") ? gSavedSettings.getU32("RenderFSAASamples") : 0;
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");
@@ -2250,12 +2254,18 @@ bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling");
+// static
+bool LLPipeline::isWaterClip()
+{
+ return (!sRenderTransparentWater || gCubeSnapshot) && !sRenderingHUDs;
+}
+
void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL);
LL_PROFILE_GPU_ZONE("updateCull"); // should always be zero GPU time, but drop a timer to flush stuff out
- bool water_clip = !sRenderTransparentWater && !sRenderingHUDs;
+ bool water_clip = isWaterClip();
if (water_clip)
{
@@ -3027,18 +3037,6 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f
{
if (drawablep && !drawablep->isDead() && assertInitialized())
{
- if (debugLoggingEnabled("AnimatedObjectsLinkset"))
- {
- LLVOVolume *vol_obj = drawablep->getVOVolume();
- if (vol_obj && vol_obj->isAnimatedObject() && vol_obj->isRiggedMesh())
- {
- std::string vobj_name = llformat("Vol%p", vol_obj);
- F32 est_tris = vol_obj->getEstTrianglesMax();
- LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " markRebuild, tris " << est_tris
- << " priority " << (S32) priority << " flag " << std::hex << flag << LL_ENDL;
- }
- }
-
if (!drawablep->isState(LLDrawable::BUILT))
{
priority = true;
@@ -5492,7 +5490,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()->isTooSlow())
)
{
drawable->clearState(LLDrawable::NEARBY_LIGHT);
@@ -5571,7 +5569,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
continue;
}
LLVOAvatar * av = light->getAvatar();
- if (av && (av->isTooComplex() || av->isInMuteList()))
+ if (av && (av->isTooComplex() || av->isInMuteList() || av->isTooSlow()))
{
// avatars that are already in the list will be removed by removeMutedAVsLights
continue;
@@ -6776,6 +6774,8 @@ void LLPipeline::renderAlphaObjects(bool rigged)
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
+ S32 sun_up = LLEnvironment::instance().getIsSunUp() ? 1 : 0;
+ U32 target_width = LLRenderTarget::sCurResX;
U32 type = LLRenderPass::PASS_ALPHA;
LLVOAvatar* lastAvatar = nullptr;
U64 lastMeshId = 0;
@@ -6798,10 +6798,18 @@ void LLPipeline::renderAlphaObjects(bool rigged)
{
if (pparams->mGLTFMaterial)
{
+ gDeferredShadowGLTFAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
mSimplePool->pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId);
}
else
{
+ gDeferredShadowAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
{
mSimplePool->uploadMatrixPalette(*pparams);
@@ -6809,18 +6817,26 @@ void LLPipeline::renderAlphaObjects(bool rigged)
lastMeshId = pparams->mSkinInfo->mHash;
}
- mSimplePool->pushBatch(*pparams, true, true, true);
+ mSimplePool->pushBatch(*pparams, true, true);
}
}
else
{
if (pparams->mGLTFMaterial)
{
+ gDeferredShadowGLTFAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
mSimplePool->pushGLTFBatch(*pparams);
}
else
{
- mSimplePool->pushBatch(*pparams, true, true, true);
+ gDeferredShadowAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
+ mSimplePool->pushBatch(*pparams, true, true);
}
}
}
@@ -6837,11 +6853,11 @@ void LLPipeline::renderMaskedObjects(U32 type, bool texture, bool batch_texture,
gGLLastMatrix = NULL;
if (rigged)
{
- mAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture, true);
+ mAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture);
}
else
{
- mAlphaMaskPool->pushMaskBatches(type, texture, batch_texture, true);
+ mAlphaMaskPool->pushMaskBatches(type, texture, batch_texture);
}
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
@@ -6855,11 +6871,11 @@ void LLPipeline::renderFullbrightMaskedObjects(U32 type, bool texture, bool batc
gGLLastMatrix = NULL;
if (rigged)
{
- mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture, true);
+ mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture);
}
else
{
- mFullbrightAlphaMaskPool->pushMaskBatches(type, texture, batch_texture, true);
+ mFullbrightAlphaMaskPool->pushMaskBatches(type, texture, batch_texture);
}
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
@@ -6927,7 +6943,8 @@ void LLPipeline::bindScreenToTexture()
static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom");
-void LLPipeline::visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32 bufferIndex) {
+void LLPipeline::visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32 bufferIndex)
+{
dst->bindTarget();
gDeferredBufferVisualProgram.bind();
gDeferredBufferVisualProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_BILINEAR, bufferIndex);
@@ -6944,7 +6961,8 @@ void LLPipeline::visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32
dst->flush();
}
-void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) {
+void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst)
+{
// luminance sample and mipmap generation
{
LL_PROFILE_GPU_ZONE("luminance sample");
@@ -7020,9 +7038,19 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst) {
static LLCachedControl<F32> dynamic_exposure_min(gSavedSettings, "RenderDynamicExposureMin", 0.125f);
static LLCachedControl<F32> dynamic_exposure_max(gSavedSettings, "RenderDynamicExposureMax", 1.3f);
+ F32 exposure_max = dynamic_exposure_max;
+ LLSettingsSky::ptr_t sky = LLEnvironment::instance().getCurrentSky();
+
+ if (sky->getReflectionProbeAmbiance() > 0.f)
+ { //not a legacy sky, use gamma as a boost to max exposure
+ exposure_max = llmax(exposure_max - 1.f, 0.f);
+ exposure_max *= sky->getGamma();
+ exposure_max += 1.f;
+ }
+
gExposureProgram.uniform1f(dt, gFrameIntervalSeconds);
gExposureProgram.uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0);
- gExposureProgram.uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, dynamic_exposure_min, dynamic_exposure_max);
+ gExposureProgram.uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, dynamic_exposure_min, exposure_max);
mScreenTriangleVB->setBuffer();
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
@@ -7039,18 +7067,25 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) {
{
LL_PROFILE_GPU_ZONE("gamma correct");
+ static LLCachedControl<bool> no_post(gSavedSettings, "RenderDisablePostProcessing", false);
+
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
// Apply gamma correction to the frame here.
- gDeferredPostGammaCorrectProgram.bind();
+
+ LLGLSLShader& shader = no_post && gFloaterTools->isAvailable() ? gNoPostGammaCorrectProgram : // no post (no gamma, no exposure, no tonemapping)
+ LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance() == 0.f ? gLegacyPostGammaCorrectProgram :
+ gDeferredPostGammaCorrectProgram;
+
+ shader.bind();
S32 channel = 0;
- gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT);
+ shader.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT);
- gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap);
+ shader.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap);
- gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, src->getWidth(), src->getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, src->getWidth(), src->getHeight());
static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f);
@@ -7058,18 +7093,19 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) {
static LLStaticHashedString s_exposure("exposure");
- gDeferredPostGammaCorrectProgram.uniform1f(s_exposure, e);
+ shader.uniform1f(s_exposure, e);
mScreenTriangleVB->setBuffer();
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
gGL.getTexUnit(channel)->unbind(src->getUsage());
- gDeferredPostGammaCorrectProgram.unbind();
+ shader.unbind();
}
dst->flush();
}
-void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst) {
+void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst)
+{
if (RenderScreenSpaceReflections && !gCubeSnapshot)
{
@@ -7095,7 +7131,8 @@ void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget*
}
}
-void LLPipeline::generateGlow(LLRenderTarget* src) {
+void LLPipeline::generateGlow(LLRenderTarget* src)
+{
if (sRenderGlow)
{
LL_PROFILE_GPU_ZONE("glow");
@@ -7192,7 +7229,8 @@ void LLPipeline::generateGlow(LLRenderTarget* src) {
}
}
-void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) {
+void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst)
+{
{
llassert(!gCubeSnapshot);
bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete();
@@ -7272,7 +7310,8 @@ void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) {
}
}
-void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst) {
+void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst)
+{
LL_PROFILE_GPU_ZONE("copyRenderTarget");
dst->bindTarget();
@@ -7292,7 +7331,8 @@ void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst) {
dst->flush();
}
-void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) {
+void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst)
+{
// Go ahead and do our glow combine here in our destination. We blit this later into the front buffer.
dst->bindTarget();
@@ -7311,7 +7351,8 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) {
dst->flush();
}
-void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) {
+void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
+{
{
bool dof_enabled =
(RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
@@ -7477,10 +7518,12 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) {
{ // combine result based on alpha
dst->bindTarget();
- if (RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete()) {
+ if (RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete())
+ {
glViewport(0, 0, dst->getWidth(), dst->getHeight());
}
- else {
+ else
+ {
gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
@@ -7515,6 +7558,7 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) {
void LLPipeline::renderFinalize()
{
+ llassert(!gCubeSnapshot);
LLVertexBuffer::unbind();
LLGLState::checkStates();
@@ -7535,22 +7579,20 @@ void LLPipeline::renderFinalize()
gGL.setColorMask(true, true);
glClearColor(0, 0, 0, 0);
- if (!gCubeSnapshot)
- {
- copyScreenSpaceReflections(&mRT->screen, &mSceneMap);
+
+ copyScreenSpaceReflections(&mRT->screen, &mSceneMap);
- generateLuminance(&mRT->screen, &mLuminanceMap);
+ generateLuminance(&mRT->screen, &mLuminanceMap);
- generateExposure(&mLuminanceMap, &mExposureMap);
+ generateExposure(&mLuminanceMap, &mExposureMap);
- gammaCorrect(&mRT->screen, &mPostMap);
+ gammaCorrect(&mRT->screen, &mPostMap);
- LLVertexBuffer::unbind();
- }
+ LLVertexBuffer::unbind();
- generateGlow(&mPostMap);
+ generateGlow(&mPostMap);
- combineGlow(&mPostMap, &mRT->screen);
+ combineGlow(&mPostMap, &mRT->screen);
gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
@@ -7562,7 +7604,8 @@ void LLPipeline::renderFinalize()
applyFXAA(&mPostMap, &mRT->screen);
LLRenderTarget* finalBuffer = &mRT->screen;
- if (RenderBufferVisualization > -1) {
+ if (RenderBufferVisualization > -1)
+ {
finalBuffer = &mPostMap;
switch (RenderBufferVisualization)
{
@@ -7663,10 +7706,18 @@ void LLPipeline::bindShadowMaps(LLGLSLShader& shader)
void LLPipeline::bindDeferredShaderFast(LLGLSLShader& shader)
{
- shader.bind();
- bindLightFunc(shader);
- bindShadowMaps(shader);
- bindReflectionProbes(shader);
+ if (shader.mCanBindFast)
+ { // was previously fully bound, use fast path
+ shader.bind();
+ bindLightFunc(shader);
+ bindShadowMaps(shader);
+ bindReflectionProbes(shader);
+ }
+ else
+ { //wasn't previously bound, use slow path
+ bindDeferredShader(shader);
+ shader.mCanBindFast = true;
+ }
}
void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
@@ -8826,8 +8877,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
stop_glerror();
- LLEnvironment& environment = LLEnvironment::instance();
-
struct CompareVertexBuffer
{
bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs)
@@ -8842,7 +8891,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
{
bool rigged = j == 1;
gDeferredShadowProgram.bind(rigged);
- LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
gGL.diffuseColor4f(1, 1, 1, 1);
@@ -8887,27 +8935,25 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha");
LL_PROFILE_GPU_ZONE("shadow alpha");
-
+ const S32 sun_up = LLEnvironment::instance().getIsSunUp() ? 1 : 0;
U32 target_width = LLRenderTarget::sCurResX;
for (int i = 0; i < 2; ++i)
{
bool rigged = i == 1;
- gDeferredShadowAlphaMaskProgram.bind(rigged);
- LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
- LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
-
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha masked");
LL_PROFILE_GPU_ZONE("shadow alpha masked");
+ gDeferredShadowAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, true, true, rigged);
}
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha blend");
LL_PROFILE_GPU_ZONE("shadow alpha blend");
- LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f);
renderAlphaObjects(rigged);
}
@@ -8915,8 +8961,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow fullbright alpha masked");
LL_PROFILE_GPU_ZONE("shadow alpha masked");
gDeferredShadowFullbrightAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
- LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, true, true, rigged);
}
@@ -8924,9 +8970,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha grass");
LL_PROFILE_GPU_ZONE("shadow alpha grass");
gDeferredTreeShadowProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF);
+
if (i == 0)
{
- LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f);
renderObjects(LLRenderPass::PASS_GRASS, true);
}
@@ -8945,8 +8992,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
{
bool rigged = i == 1;
gDeferredShadowGLTFAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up);
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
- LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
@@ -9449,14 +9496,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++)
- {
- mRT->shadow[j].bindTarget();
- mRT->shadow[j].clear();
- mRT->shadow[j].flush();
- }
+ skipRenderingShadows();
}
else
{
@@ -9512,7 +9552,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) && !gCubeSnapshot)
@@ -10051,11 +10092,79 @@ void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, bool texture)
}
}
-static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
+void LLPipeline::profileAvatar(LLVOAvatar* avatar, bool profile_attachments)
+{
+ if (gGLManager.mGLVersion < 3.25f)
+ { // profiling requires GL 3.3 or later
+ return;
+ }
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+
+ // don't continue to profile an avatar that is known to be too slow
+ llassert(!avatar->isTooSlow());
+
+ LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ mRT->deferredScreen.bindTarget();
+ mRT->deferredScreen.clear();
+
+ if (!profile_attachments)
+ {
+ // profile entire avatar all at once and readback asynchronously
+ avatar->placeProfileQuery();
+
+ LLTimer cpu_timer;
+
+ generateImpostor(avatar, false, true);
+
+ avatar->mCPURenderTime = (F32)cpu_timer.getElapsedTimeF32() * 1000.f;
+
+ avatar->readProfileQuery(5); // allow up to 5 frames of latency
+ }
+ else
+ {
+ // profile attachments one at a time
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ for (iter = begin;
+ iter != end;
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object)
+ {
+ // use gDebugProgram to do the GPU queries
+ gDebugProgram.clearStats();
+ gDebugProgram.placeProfileQuery(true);
+
+ generateImpostor(avatar, false, true, attached_object);
+ gDebugProgram.readProfileQuery(true, true);
+
+ attached_object->mGPURenderTime = gDebugProgram.mTimeElapsed / 1000000.f;
+ }
+ }
+ }
+ }
+
+ mRT->deferredScreen.flush();
-void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
+ if (cur_shader)
+ {
+ cur_shader->bind();
+ }
+}
+
+void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool for_profile, LLViewerObject* specific_attachment)
{
- LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
LL_PROFILE_GPU_ZONE("generateImpostor");
LLGLState::checkStates();
@@ -10073,19 +10182,19 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
assertInitialized();
// previews can't be muted or impostered
- bool visually_muted = !preview_avatar && avatar->isVisuallyMuted();
+ bool visually_muted = !for_profile && !preview_avatar && avatar->isVisuallyMuted();
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
<< " is " << ( visually_muted ? "" : "not ") << "visually muted"
<< LL_ENDL;
- bool too_complex = !preview_avatar && avatar->isTooComplex();
+ bool too_complex = !for_profile && !preview_avatar && avatar->isTooComplex();
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
<< " is " << ( too_complex ? "" : "not ") << "too complex"
<< LL_ENDL;
- pushRenderTypeMask();
-
- if (visually_muted || too_complex)
- {
+ pushRenderTypeMask();
+
+ if (visually_muted || too_complex)
+ {
// only show jelly doll geometry
andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR,
LLPipeline::RENDER_TYPE_CONTROL_AV,
@@ -10103,6 +10212,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
RENDER_TYPE_TREE,
RENDER_TYPE_VOIDWATER,
RENDER_TYPE_WATER,
+ RENDER_TYPE_ALPHA_POST_WATER,
RENDER_TYPE_PASS_GRASS,
RENDER_TYPE_HUD,
RENDER_TYPE_PARTICLES,
@@ -10112,6 +10222,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
);
}
+ if (specific_attachment && specific_attachment->isHUDAttachment())
+ { //enable HUD rendering
+ setRenderTypeMask(RENDER_TYPE_HUD, END_RENDER_TYPES);
+ }
+
S32 occlusion = sUseOcclusion;
sUseOcclusion = 0;
@@ -10168,20 +10283,30 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
}
else
{
- LLVOAvatar::attachment_map_t::iterator iter;
- for (iter = avatar->mAttachmentPoints.begin();
- iter != avatar->mAttachmentPoints.end();
- ++iter)
+ if (specific_attachment)
{
- LLViewerJointAttachment *attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
+ markVisible(specific_attachment->mDrawable->getSpatialBridge(), *viewer_camera);
+ }
+ else
+ {
+ LLVOAvatar::attachment_map_t::iterator iter;
+ LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin();
+ LLVOAvatar::attachment_map_t::iterator end = avatar->mAttachmentPoints.end();
+
+ for (iter = begin;
+ iter != end;
+ ++iter)
{
- LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object)
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+ LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object)
+ {
+ markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+ }
}
}
}
@@ -10251,25 +10376,28 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
- if (!avatar->mImpostor.isComplete())
- {
- avatar->mImpostor.allocate(resX, resY, GL_RGBA, true);
+ if (!for_profile)
+ {
+ if (!avatar->mImpostor.isComplete())
+ {
+ avatar->mImpostor.allocate(resX, resY, GL_RGBA, true);
- if (LLPipeline::sRenderDeferred)
- {
- addDeferredAttachments(avatar->mImpostor, true);
- }
-
- gGL.getTexUnit(0)->bind(&avatar->mImpostor);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight())
- {
- avatar->mImpostor.resize(resX,resY);
- }
+ if (LLPipeline::sRenderDeferred)
+ {
+ addDeferredAttachments(avatar->mImpostor, true);
+ }
+
+ gGL.getTexUnit(0)->bind(&avatar->mImpostor);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+ else if (resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight())
+ {
+ avatar->mImpostor.resize(resX, resY);
+ }
- avatar->mImpostor.bindTarget();
+ avatar->mImpostor.bindTarget();
+ }
}
F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
@@ -10279,9 +10407,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
LLDrawPoolAvatar::sMinimumAlpha = 0.f;
}
- if (preview_avatar)
+ if (preview_avatar || for_profile)
{
- // previews don't care about imposters
+ // previews and profiles don't care about imposters
renderGeomDeferred(camera);
renderGeomPostDeferred(camera);
}
@@ -10310,6 +10438,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
+ if (!for_profile)
{ //create alpha mask based on depth buffer (grey out if muted)
if (LLPipeline::sRenderDeferred)
{
@@ -10371,7 +10500,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
gGL.popMatrix();
}
- if (!preview_avatar)
+ if (!preview_avatar && !for_profile)
{
avatar->mImpostor.flush();
avatar->setImpostorDim(tdim);
@@ -10388,7 +10517,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.popMatrix();
- if (!preview_avatar)
+ if (!preview_avatar && !for_profile)
{
avatar->mNeedsImpostorUpdate = FALSE;
avatar->cacheImpostorValues();
@@ -10713,9 +10842,32 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )
}
}
+void LLPipeline::skipRenderingShadows()
+{
+ LLGLDepthTest depth(GL_TRUE);
+
+ for (S32 j = 0; j < 4; j++)
+ {
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
+ }
+}
+
+void LLPipeline::handleShadowDetailChanged()
+{
+ if (RenderShadowDetail > gSavedSettings.getS32("RenderShadowDetail"))
+ {
+ skipRenderingShadows();
+ }
+ else
+ {
+ LLViewerShaderMgr::instance()->setShaders();
+ }
+}
+
void LLPipeline::overrideEnvironmentMap()
{
//mReflectionMapManager.mProbes.clear();
//mReflectionMapManager.addProbe(LLViewerCamera::instance().getOrigin());
}
-
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 64a26c264a..4654f05694 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -132,7 +132,17 @@ public:
bool allocateShadowBuffer(U32 resX, U32 resY);
void resetVertexBuffers(LLDrawable* drawable);
- void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false);
+
+ // perform a profile of the given avatar
+ // if profile_attachments is true, run a profile for each attachment
+ void profileAvatar(LLVOAvatar* avatar, bool profile_attachments = false);
+
+ // generate an impostor for the given avatar
+ // preview_avatar - if true, a preview window render is being performed
+ // for_profile - if true, a profile is being performed, do not update actual impostor
+ // specific_attachment - specific attachment to profile, or nullptr to profile entire avatar
+ void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false, bool for_profile = false, LLViewerObject* specific_attachment = nullptr);
+
void bindScreenToTexture();
void renderFinalize();
void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst);
@@ -366,6 +376,8 @@ public:
bool hasRenderType(const U32 type) const;
bool hasAnyRenderType(const U32 type, ...) const;
+ static bool isWaterClip();
+
void setRenderTypeMask(U32 type, ...);
// This is equivalent to 'setRenderTypeMask'
//void orRenderTypeMask(U32 type, ...);
@@ -435,6 +447,7 @@ public:
void skipRenderingOfTerrain( bool flag );
void hideObject( const LLUUID& id );
void restoreHiddenObject( const LLUUID& id );
+ void handleShadowDetailChanged();
LLReflectionMapManager mReflectionMapManager;
void overrideEnvironmentMap();
@@ -449,6 +462,7 @@ private:
void connectRefreshCachedSettingsSafe(const std::string name);
void hideDrawable( LLDrawable *pDrawable );
void unhideDrawable( LLDrawable *pDrawable );
+ void skipRenderingShadows();
public:
enum {GPU_CLASS_MAX = 3 };
@@ -591,7 +605,6 @@ public:
RENDER_DEBUG_PHYSICS_SHAPES = 0x02000000,
RENDER_DEBUG_NORMALS = 0x04000000,
RENDER_DEBUG_LOD_INFO = 0x08000000,
- RENDER_DEBUG_RENDER_COMPLEXITY = 0x10000000,
RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used
RENDER_DEBUG_TEXEL_DENSITY = 0x40000000,
RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000,
@@ -765,7 +778,6 @@ protected:
U64 mOldRenderDebugMask;
std::stack<U32> mRenderDebugFeatureStack;
-
/////////////////////////////////////////////
//
//
@@ -959,6 +971,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 8bb3feaeb0..6efe302f30 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -983,12 +983,15 @@
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" />
+ <color
name="OutfitSnapshotMacMask"
value="0.115 0.115 0.115 1"/>
- <color
- name="OutfitSnapshotMacMask2"
- value="0.1 0.1 0.1 1"/>
+ <color
+ name="OutfitSnapshotMacMask2"
+ value="0.1 0.1 0.1 1"/>
</colors>
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index bdf12d73fc..61257466aa 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
new file mode 100644
index 0000000000..91baf849c8
--- /dev/null
+++ b/indra/newview/skins/default/textures/toolbar_icons/performance.png
Binary files differ
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_adjust_environment.xml b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
index ca5c7fe264..aef923feb2 100644
--- a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
+++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
@@ -239,7 +239,7 @@
layout="topleft"
left_delta="-5"
top_pad="15"
- width="80">Scene Gamma:</text>
+ width="80">Brightness:</text>
<slider decimal_digits="2"
follows="left|top"
height="16"
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..d1a1119f77
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_performance.xml
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ height="642"
+ layout="topleft"
+ name="performance"
+ save_rect="true"
+ reuse_instance="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="autoadjustments_subpanel"
+ layout="topleft"
+ left="10"
+ top="5">
+ <text
+ follows="left|top"
+ font="SansSerifBoldLarge"
+ text_color="White"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="auto_adj_lbl"
+ top="7"
+ width="375">
+ Auto-adjust settings (recommended)
+ </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.
+ </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="settings_subpanel"
+ layout="topleft"
+ top_pad="10">
+ <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>
+ <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 22e889a99c..fd80673903 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"
@@ -459,8 +460,8 @@
label_width="185"
layout="topleft"
left="420"
- min_val="1"
- max_val="2"
+ min_val="0"
+ max_val="4"
name="ObjectMeshDetail"
show_text="false"
top_delta="16"
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 4a92bdc601..df067d2b88 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"
@@ -1492,7 +1501,28 @@ function="World.EnvPreset"
function="ToggleControl"
parameter="ShowSelectionBeam" />
</menu_item_check>
-
+ <menu_item_check
+ label="Highlight Transparent"
+ name="Highlight Transparent"
+ shortcut="control|alt|T"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="View.CheckHighlightTransparent" />
+ <menu_item_check.on_click
+ function="View.HighlightTransparent" />
+ </menu_item_check>
+ <menu_item_separator/>
+
+ <menu_item_check
+ label="No Post"
+ name="No Post">
+ <menu_item_check.on_check
+ control="RenderDisablePostProcessing" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDisablePostProcessing" />
+ </menu_item_check>
+
<menu_item_separator/>
<menu_item_check
@@ -1902,16 +1932,6 @@ function="World.EnvPreset"
parameter="HideSelectedObjects" />
</menu_item_check>
<menu_item_check
- label="Highlight Transparent"
- name="Highlight Transparent"
- shortcut="control|alt|T"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="View.CheckHighlightTransparent" />
- <menu_item_check.on_click
- function="View.HighlightTransparent" />
- </menu_item_check>
- <menu_item_check
label="Show Mouselook Crosshairs"
name="ShowCrosshairs">
<menu_item_check.on_check
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index bf67118eac..4949075f2d 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 &gt; 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.
@@ -12029,6 +12064,20 @@ If you want others to see this object, remove it and re-attach it to an avatar a
yestext="OK"/>
</notification>
+ <notification
+ icon="alertmodal.tga"
+ name="EnableAutoFPSWarning"
+ type="alertmodal">
+You are about to enable AutoFPS. All unsaved graphics settings will be lost.
+
+Would you like to save them first?
+ <tag>confirm</tag>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
<notification
icon="notifytip.tga"
name="MaterialCreated"
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..904ce1cc52
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_performance_autoadjustments.xml
@@ -0,0 +1,387 @@
+<?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="18"
+ layout="topleft"
+ left_pad="0"
+ valign="center"
+ halign="center"
+ top="6"
+ name="back_lbl"
+ width="32">
+ Back
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ text_color="white"
+ height="20"
+ layout="topleft"
+ left="20"
+ top_pad="15"
+ name="settings_title"
+ width="300">
+ Auto-adjust settings
+ </text>
+ <button
+ follows="top|left"
+ height="23"
+ label="Reset to recommended settings"
+ layout="topleft"
+ left="360"
+ name="defaults_btn"
+ top_delta="0"
+ width="200"/>
+ <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="115"
+ 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="left|top"
+ left_pad="25"
+ 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" />
+ <text
+ follows="left|top"
+ text_color="White"
+ height="20"
+ layout="topleft"
+ name="display_desc"
+ top_delta="5"
+ left_pad="15"
+ wrap="true"
+ width="225">
+ Your display supports up to [FPS_LIMIT] fps.
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ text_color="White"
+ height="20"
+ layout="topleft"
+ left="20"
+ name="settings_desc"
+ top_pad="15"
+ wrap="true"
+ width="115">
+ Settings affect
+ </text>
+ <combo_box
+ follows="top|left"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_pad="25"
+ control_name="TuningFPSStrategy"
+ name="TuningFPSStrategy"
+ width="160">
+ <combo_box.item
+ label="Avatars Only"
+ name="av_only"
+ value="0" />
+ <combo_box.item
+ label="Avatars and World"
+ name="av_and_scene"
+ value="1" />
+ <combo_box.item
+ label="World Only"
+ name="scene_only"
+ value="2" />
+ </combo_box>
+ <button
+ follows="top|left"
+ height="22"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="Auto-adjust now"
+ layout="topleft"
+ top_pad="15"
+ left="20"
+ name="start_autotune"
+ tool_tip="The viewer will attempt to adjust settings to meet the target FPS then stop."
+ width="124"/>
+ <button
+ follows="top|left"
+ height="22"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="Cancel"
+ layout="topleft"
+ left_pad="15"
+ name="stop_autotune"
+ tool_tip="Stop adjusting settings."
+ width="90"/>
+ <text
+ follows="left|top"
+ text_color="Yellow"
+ height="20"
+ layout="topleft"
+ name="wip_desc"
+ top_delta="5"
+ left_pad="20"
+ wrap="true"
+ width="115">
+ Working on it...
+ </text>
+ <check_box
+ control_name="AutoTuneLock"
+ follows="top|left"
+ height="20"
+ initial_value="true"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ is_toggle="true"
+ label="Adjust continuously"
+ layout="topleft"
+ left="17"
+ top_pad="10"
+ name="AutoTuneContinuous"
+ tool_tip="The viewer will continually adapt the settings to meet the target FPS until stopped even with the floater closed."
+ width="64">
+ </check_box>
+ <radio_group
+ control_name="KeepAutoTuneLock"
+ enabled_control="AutoTuneLock"
+ height="50"
+ layout="topleft"
+ follows="top|left"
+ name="autotune_lock_type"
+ top_pad="5"
+ left_delta="15"
+ width="120">
+ <radio_item
+ height="16"
+ label="This login session only"
+ layout="topleft"
+ name="one_session_lock"
+ value="0"
+ width="120" />
+ <radio_item
+ height="16"
+ label="Future login sessions"
+ layout="topleft"
+ name="next_session_lock"
+ value="1"
+ width="120" />
+ </radio_group>
+ <view_border
+ bevel_style="in"
+ height="0"
+ layout="topleft"
+ name="border_vsync"
+ top_pad="3"
+ left="20"
+ width="540"/>
+ <check_box
+ control_name="RenderVSyncEnable"
+ height="16"
+ left="17"
+ initial_value="true"
+ label="Enable VSync"
+ label_text.text_color="White"
+ layout="topleft"
+ top_pad="12"
+ name="vsync"
+ tool_tip="Enable Vertical synchronization to reduce screen tearing and stuttering."
+ width="315" />
+ <text
+ follows="left|top"
+ font="SansSerifSmall"
+ text_color="White"
+ height="18"
+ layout="topleft"
+ left="20"
+ top_pad="15"
+ name="vsync_desc"
+ width="580">
+ Matches monitor refresh rate with frame rate.
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifSmall"
+ text_color="White"
+ height="18"
+ layout="topleft"
+ top_pad="3"
+ left="20"
+ name="vsync_desc_limit"
+ width="580">
+ Note: Turning on VSync limits frame rate to [FPS_LIMIT] fps.
+ </text>
+ <view_border
+ bevel_style="in"
+ height="0"
+ layout="topleft"
+ name="border1"
+ top_pad="10"
+ 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="15"
+ 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..cd3f610a92
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_performance_complexity.xml
@@ -0,0 +1,106 @@
+<?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="18"
+ layout="topleft"
+ left_pad="0"
+ valign="center"
+ halign="center"
+ top="6"
+ name="back_lbl"
+ width="32">
+ Back
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ text_color="white"
+ height="20"
+ layout="topleft"
+ left="20"
+ top_pad="15"
+ 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..2fddcb3b9e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_performance_huds.xml
@@ -0,0 +1,95 @@
+<?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="18"
+ layout="topleft"
+ left_pad="0"
+ valign="center"
+ halign="center"
+ top="6"
+ name="back_lbl"
+ width="32">
+ Back
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ text_color="White"
+ height="20"
+ layout="topleft"
+ left="20"
+ top_pad="15"
+ 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..cb795e59a9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_performance_nearby.xml
@@ -0,0 +1,216 @@
+<?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="18"
+ layout="topleft"
+ left_pad="0"
+ valign="center"
+ halign="center"
+ top="6"
+ name="back_lbl"
+ width="32">
+ Back
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ text_color="White"
+ height="20"
+ layout="topleft"
+ left="20"
+ top_pad="15"
+ 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..83db17b679
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_performance_preferences.xml
@@ -0,0 +1,494 @@
+<?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="18"
+ layout="topleft"
+ left_pad="0"
+ valign="center"
+ halign="center"
+ top="6"
+ name="back_lbl"
+ width="32">
+ Back
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifLarge"
+ text_color="white"
+ height="20"
+ layout="topleft"
+ left="20"
+ top_pad="15"
+ 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="-35"
+ width="200"/>
+ <button
+ follows="top|left"
+ height="23"
+ label="Reset to recommended settings"
+ layout="topleft"
+ left="350"
+ name="defaults_btn"
+ top_pad="10"
+ width="210"/>
+ <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 &amp; 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">
+ Shadows
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerifSmall"
+ text_color="White"
+ height="18"
+ layout="topleft"
+ top_delta="0"
+ left="160"
+ name="enhancements_desc"
+ width="350">
+ Shadows significantly improve visual quality but can reduce speed.
+ </text>
+ <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">
+ Shadow Detail:
+ </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 transparent water may 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>
+ <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 38d364cf9a..74a44b6b09 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -231,6 +231,18 @@
m
</text>
+ <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"
tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
@@ -246,7 +258,7 @@
max_val="101"
name="IndirectMaxComplexity"
show_text="false"
- top_delta="36"
+ top_delta="40"
width="300">
<slider.commit_callback
function="Pref.UpdateIndirectMaxComplexity"
diff --git a/indra/newview/skins/default/xui/en/panel_presets_pulldown.xml b/indra/newview/skins/default/xui/en/panel_presets_pulldown.xml
index b87dda2315..b3d165c4fd 100644
--- a/indra/newview/skins/default/xui/en/panel_presets_pulldown.xml
+++ b/indra/newview/skins/default/xui/en/panel_presets_pulldown.xml
@@ -8,7 +8,7 @@
border="false"
chrome="true"
follows="bottom"
- height="155"
+ height="185"
layout="topleft"
name="presets_pulldown"
width="225">
@@ -57,7 +57,7 @@
width="215" />
<button
name="open_prefs_btn"
- label="Open Graphics Preferences"
+ label="Graphics Preferences"
tool_tip = "Bring up graphics prefs"
top_delta="5"
left="15"
@@ -66,4 +66,15 @@
<button.commit_callback
function="Presets.GoGraphicsPrefs" />
</button>
+ <button
+ name="open_autofps_btn"
+ label="Auto-FPS settings"
+ tool_tip = "Bring up auto-adjust settings"
+ top_pad="5"
+ left="15"
+ height="20"
+ width="200">
+ <button.commit_callback
+ function="Presets.GoAutofpsPrefs" />
+ </button>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
index 622c999254..e90e6caf84 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
@@ -223,7 +223,7 @@
left_delta="-5"
top_delta="25"
width="80">
- Scene Gamma:
+ Brightness:
</text>
<slider
decimal_digits="2"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 62b26da552..9c634b661a 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -4163,6 +4163,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>
@@ -4195,6 +4196,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>
@@ -4296,7 +4298,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.