diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index ac202090622d7af7f8c1c11a73a8c6aa8ad7257f..c03b2e93f477fa546e7d22f5d2729629e75eea50 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -86,8 +86,12 @@ extern thread_local bool gProfilerEnabled;
         #define TRACY_ONLY_IPV4      1
         #include "Tracy.hpp"
 
-        // Disable memory tracing when enabled, but enabled 
+        // Enable OpenGL profiling
         #define LL_PROFILER_ENABLE_TRACY_OPENGL 1
+
+        // Enable RenderDoc labeling
+        #define LL_PROFILER_ENABLE_RENDER_DOC 0
+
     #endif
 
     #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
@@ -153,8 +157,6 @@ extern thread_local bool gProfilerEnabled;
 // disable memory tracking (incompatible with GPU tracing
 #define LL_PROFILE_ALLOC(ptr, size)             (void)(ptr); (void)(size);
 #define LL_PROFILE_FREE(ptr)                    (void)(ptr);
-
-#define LL_LABEL_OBJECT_GL(type, name, length, label) glObjectLabel(type, name, length, label)
 #else
 #define LL_PROFILE_GPU_ZONE(name)        (void)name;
 #define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
@@ -173,6 +175,12 @@ extern thread_local bool gProfilerEnabled;
 
 #endif
 
+#if LL_PROFILER_ENABLE_RENDER_DOC
+#define LL_LABEL_OBJECT_GL(type, name, length, label) glObjectLabel(type, name, length, label)
+#else
+#define LL_LABEL_OBJECT_GL(type, name, length, label)
+#endif
+
 #include "llprofilercategories.h"
 
 #endif // LL_PROFILER_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 0a834b28e387923105b47a5680457cba7c1325a0..661ea6c4fa7ff30dabce56175b8987e92c2e6190 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -505,7 +505,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
         unbind();
     }
 
-#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
     setLabel(mName.c_str());
 #endif
 
@@ -1792,9 +1792,8 @@ void LLShaderUniforms::apply(LLGLSLShader* shader)
     }
 }
 
-#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
 void LLGLSLShader::setLabel(const char* label) {
     LL_LABEL_OBJECT_GL(GL_PROGRAM, mProgramObject, strlen(label), label);
 }
-
 #endif
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 0df0531dcec6a93ddd653e1beec4ed9ae0f27eb8..57bd4987bce242cfca89bfb6aa0cb560c16c38e4 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -300,7 +300,7 @@ class LLGLSLShader
     // this pointer should be set to whichever shader represents this shader's rigged variant
     LLGLSLShader* mRiggedVariant = nullptr;
 
-	#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+	#ifdef LL_PROFILER_ENABLE_RENDER_DOC
     void setLabel(const char* label);
 	#endif
 
@@ -315,7 +315,7 @@ extern LLGLSLShader			gSolidColorProgram;
 //Alpha mask shader (declared here so llappearance can access properly)
 extern LLGLSLShader			gAlphaMaskProgram;
 
-#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
 #define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader)
 #else
 #define LL_SET_SHADER_LABEL(shader, label)
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index f51000b9a6e4aec32ec43d020a12193b7aa1a64e..fc24c6846d8fc8ac4594dffc04da88ee75e595d7 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -574,7 +574,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
 	}
 }
 
-#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
 void LLVertexBuffer::setLabel(const char* label) {
 	LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label);
 }
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 99b8b54d6987fc0ceea942c3709feb6ca3bec662..e846ab70e2a0fe414959c8cc5c6ba9f866f69386 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -303,7 +303,7 @@ class LLVertexBuffer : public LLRefCount
 	//for debugging, validate data in given range is valid
 	void validateRange(U32 start, U32 end, U32 count, U32 offset) const;
 
-	#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+	#ifdef LL_PROFILER_ENABLE_RENDER_DOC
 	void setLabel(const char* label);
 	#endif
 	
@@ -376,7 +376,7 @@ class LLVertexBuffer : public LLRefCount
 	static U32 sSetCount;
 };
 
-#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+#ifdef LL_PROFILER_ENABLE_RENDER_DOC
 #define LL_LABEL_VERTEX_BUFFER(buf, name) buf->setLabel(name)
 #else
 #define LL_LABEL_VERTEX_BUFFER(buf, name)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 71611a58bc398c05275929ba72d4089932f480e9..9f10e5cac58a6e4f421ee089acb468da313e633e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10563,7 +10563,7 @@
   <key>RenderUseTriStrips</key>
   <map>
     <key>Comment</key>
-    <string>Use triangle strips for rendering prims.</string>
+    <string>DEPRECATED - now always assumed to be false - Use triangle strips for rendering prims.</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f3f512a6f238525fac781c36fc865d06caf796ab..efc272678509f9aaa02662f746fad5318886c015 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1311,23 +1311,6 @@ void LLAppViewer::initMaxHeapSize()
     LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
 }
 
-static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
-static LLTrace::BlockTimerStatHandle FTM_SLEEP1("Sleep1");
-static LLTrace::BlockTimerStatHandle FTM_SLEEP2("Sleep2");
-static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield");
-
-static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache");
-static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode");
-static LLTrace::BlockTimerStatHandle FTM_FETCH("Image Fetch");
-
-static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
-static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
-static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
-static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump");
-static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service");
-static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback");
-static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot");
-static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");
 
 // externally visible timers
 LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
@@ -1406,7 +1389,7 @@ bool LLAppViewer::doFrame()
 
 		if (gViewerWindow)
 		{
-			LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_APP("System Messages");
 			gViewerWindow->getWindow()->processMiscNativeEvents();
 		}
 
@@ -1417,7 +1400,7 @@ bool LLAppViewer::doFrame()
 
 		if (gViewerWindow)
 		{
-			LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_APP("System Messages");
 			if (!restoreErrorTrap())
 			{
 				LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
@@ -1480,7 +1463,7 @@ bool LLAppViewer::doFrame()
 				}
 
 				{
-					LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle"); //LL_RECORD_BLOCK_TIME(FTM_IDLE);
+					LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle");
 					idle();
 				}
 
@@ -1541,7 +1524,7 @@ bool LLAppViewer::doFrame()
 			static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1);
 			if(yield_time >= 0)
 			{
-				LL_RECORD_BLOCK_TIME(FTM_YIELD);
+                LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Yield");
 				LL_PROFILE_ZONE_NUM( yield_time )
 				ms_sleep(yield_time);
 			}
@@ -1594,7 +1577,7 @@ bool LLAppViewer::doFrame()
 				work_pending += updateTextureThreads(max_time);
 
 				{
-					LL_RECORD_BLOCK_TIME(FTM_LFS);
+                    LL_PROFILE_ZONE_NAMED_CATEGORY_APP("LFS Thread");
  					io_pending += LLLFSThread::updateClass(1);
 				}
 
@@ -1663,15 +1646,15 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)
 {
 	S32 work_pending = 0;
 	{
-		LL_RECORD_BLOCK_TIME(FTM_TEXTURE_CACHE);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Texture Cache");
  		work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
 	}
 	{
-		LL_RECORD_BLOCK_TIME(FTM_DECODE);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Decode");
 	 	work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
 	}
 	{
-		LL_RECORD_BLOCK_TIME(FTM_FETCH);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Fetch");
 	 	work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
 	}
 	return work_pending;
@@ -4787,7 +4770,7 @@ void LLAppViewer::idle()
 		}
 
 		{
-			LL_RECORD_BLOCK_TIME(FTM_AGENT_AUTOPILOT);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Autopilot");
 			// Handle automatic walking towards points
 			gAgentPilot.updateTarget();
 			gAgent.autoPilot(&yaw);
@@ -4803,7 +4786,7 @@ void LLAppViewer::idle()
 							|| (agent_force_update_time > (1.0f / (F32) AGENT_FORCE_UPDATES_PER_SECOND));
 		if (force_update || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
 		{
-			LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_RECORD_BLOCK_TIME(FTM_AGENT_UPDATE);
+			LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
 			// Send avatar and camera info
 			mLastAgentControlFlags = gAgent.getControlFlags();
 			mLastAgentForceUpdate = force_update ? 0 : agent_force_update_time;
@@ -4854,7 +4837,7 @@ void LLAppViewer::idle()
 
 	if (!gDisconnected)
 	{
-		LL_RECORD_BLOCK_TIME(FTM_NETWORK);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Network");
 
 	    ////////////////////////////////////////////////
 	    //
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index bfcc24fd13dd4ef615e3f8851c33efd9936321df..b3ae673aed6c42c855fda8fb692a568af6df1d4d 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -566,17 +566,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
 		}
 	}
 	
-    if (params.mGroup)
-    {
-        params.mGroup->rebuildMesh();
-    }
-
-    LLGLDisable cull(params.mGLTFMaterial && params.mGLTFMaterial->mDoubleSided ? GL_CULL_FACE : 0);
-
-    //LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
+    //if (params.mGroup) // TOO LATE!
+    //{
+    //    params.mGroup->rebuildMesh();
+    //}
 
     params.mVertexBuffer->setBufferFast(mask);
-    params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+    params.mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 
 	if (tex_setup)
 	{
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index cc5d2ddb26992fcc56e678794a2c3bbc4a67b941..2c8d6ff65295fc0a45378b76de58256c793ab1b0 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -204,7 +204,7 @@ class LLRenderPass : public LLDrawPool
 		NUM_RENDER_TYPES,
 	};
 
-	#ifdef LL_PROFILER_ENABLE_TRACY_OPENGL
+	#ifdef LL_PROFILER_ENABLE_RENDER_DOC
     static inline const char* lookupPassName(U32 pass)
     {
         switch (pass)
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index aa8d4d167e5c029f827f89fb2995e3dc683a3701..71b568a436d28288f41a4e0481f681f52d8152d6 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -406,7 +406,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
                         params.mGroup->rebuildMesh();
                     }
                     params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask);
-                    params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+                    params.mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
                 }
             }
         }
@@ -435,7 +435,7 @@ inline void Draw(LLDrawInfo* draw, U32 mask)
 {
     draw->mVertexBuffer->setBufferFast(mask);
     LLRenderPass::applyModelMatrix(*draw);
-	draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);                    
+	draw->mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);                    
 }
 
 bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material)
@@ -531,7 +531,7 @@ void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
 {
     LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
     draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
-	draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
+	draw->mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
 }
 
 
@@ -678,7 +678,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
 
                     if (current_shader != target_shader)
                     {
-                        gPipeline.bindDeferredShader(*target_shader);
+                        target_shader->bind();
+                        //gPipeline.bindDeferredShader(*target_shader);
                     }
 
                     params.mGLTFMaterial->bind(target_shader);
@@ -729,7 +730,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
 
                         if (current_shader != target_shader)
                         {
-                            gPipeline.bindDeferredShader(*target_shader);
+                            //gPipeline.bindDeferredShader(*target_shader);
+                            target_shader->bind();
                         }
                     }
                     else if (!params.mFullbright)
@@ -750,7 +752,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
                     if (current_shader != target_shader)
                     {// If we need shaders, and we're not ALREADY using the proper shader, then bind it
                     // (this way we won't rebind shaders unnecessarily).
-                        gPipeline.bindDeferredShader(*target_shader);
+                        //gPipeline.bindDeferredShader(*target_shader);
+                        target_shader->bind();
                     }
 
                     LLVector4 spec_color(1, 1, 1, 1);
@@ -821,7 +824,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
                     }
 
                     params.mVertexBuffer->setBufferFast(drawMask);
-                    params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+                    params.mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 
                     if (reset_minimum_alpha)
                     {
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 75917d0ae3cc3e23fff14e71ba186067006b8365..86473beace5afd52c2ed0339a45e13cd0e6c8d9a 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -562,8 +562,7 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
 			params.mGroup->rebuildMesh();
 		}
 		params.mVertexBuffer->setBuffer(mask);
-		params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
-		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
+		params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 	}
 }
 
@@ -1439,7 +1438,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
 		params.mGroup->rebuildMesh();
 	}
 	params.mVertexBuffer->setBufferFast(mask);
-	params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+	params.mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 
     if (tex_setup)
 	{
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index d97f0714ef30f5e6ec67343786e206b0336fb408..1c9fb55d06795e8161c8ba1326f72e097c381cc7 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -263,7 +263,7 @@ void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool
 	//LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
 
 	params.mVertexBuffer->setBufferFast(mask);
-	params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+	params.mVertexBuffer->drawRangeFast(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
 
 	if (tex_setup)
 	{
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 528675072b94fc1e4c291d83104cbb397a00e540..6557bcb81dbb0d080cefd987f5b45d1a2658d729 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -2460,13 +2460,8 @@ S32 LLFace::pushVertices(const U16* index_array) const
 {
 	if (mIndicesCount)
 	{
-		U32 render_type = LLRender::TRIANGLES;
-		if (mDrawInfo)
-		{
-			render_type = mDrawInfo->mDrawMode;
-		}
-		mVertexBuffer->drawRange(render_type, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex);
-		gPipeline.addTrianglesDrawn(mIndicesCount, render_type);
+		mVertexBuffer->drawRange(LLRender::TRIANGLES, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex);
+		gPipeline.addTrianglesDrawn(mIndicesCount);
 	}
 
 	return mIndicesCount;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 61e9d261f7f6027b51c4e5a1588c93a31643cfe9..7d1bc7fc483a296eb593c856934d998aecb70c6b 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -4049,7 +4049,6 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
 	mGroup(NULL),
 	mFace(NULL),
 	mDistance(0.f),
-	mDrawMode(LLRender::TRIANGLES),
 	mMaterial(NULL),
 	mShaderMask(0),
 	mSpecColor(1.0f, 1.0f, 1.0f, 0.5f),
@@ -4058,8 +4057,7 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
 	mHasGlow(FALSE),
 	mEnvIntensity(0.0f),
 	mAlphaMaskCutoff(0.5f),
-	mDiffuseAlphaMode(0),
-	mSelected(selected)
+	mDiffuseAlphaMode(0)
 {
 	mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);
 	
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 0d16b818f120830795d6b39427d605a145d714a6..692aae6fa42d059aea2fdb138b773ff23f804399 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -97,7 +97,6 @@ class LLDrawInfo : public LLRefCount
     // used to update the decode priority of textures in this DrawInfo
     std::vector<F32> mTextureListVSize;
 
-	S32 mDebugColor;
 	const LLMatrix4* mTextureMatrix;
 	const LLMatrix4* mModelMatrix;
 	U16 mStart;
@@ -107,13 +106,14 @@ class LLDrawInfo : public LLRefCount
 	BOOL mFullbright;
 	U8 mBump;
 	U8 mShiny;
+    U8 mTextureTimer = 0;
 	BOOL mParticle;
 	F32 mPartSize;
 	F32 mVSize;
 	LLSpatialGroup* mGroup;
 	LL_ALIGN_16(LLFace* mFace); //associated face
 	F32 mDistance;
-	U32 mDrawMode;
+    S32 mDebugColor;
 
     // Material pointer here is likely for debugging only and are immaterial (zing!)
     LLMaterialPtr mMaterial; 
@@ -136,11 +136,9 @@ class LLDrawInfo : public LLRefCount
 	F32  mEnvIntensity;
 	F32  mAlphaMaskCutoff;
 	U8   mDiffuseAlphaMode;
-	bool mSelected;
     LLPointer<LLVOAvatar> mAvatar = nullptr;
     LLMeshSkinInfo* mSkinInfo = nullptr;
 
-
 	struct CompareTexture
 	{
 		bool operator()(const LLDrawInfo& lhs, const LLDrawInfo& rhs)
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 98627f83138ad96ac0636ed8de272b0c562f07cb..0c9324cc4295388c7cf238f9494490d22ec53719 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -689,7 +689,6 @@ void settings_setup_listeners()
 	setting_setup_signal_listener(gSavedSettings, "OctreeAlphaDistanceFactor", handleRepartition);
 	setting_setup_signal_listener(gSavedSettings, "OctreeAttachmentSizeFactor", handleRepartition);
 	setting_setup_signal_listener(gSavedSettings, "RenderMaxTextureIndex", handleSetShaderChanged);
-	setting_setup_signal_listener(gSavedSettings, "RenderUseTriStrips", handleResetVertexBuffersChanged);
 	setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized);
 	setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged);
 	setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 7709054d24f994d1141e3c2e779fdf920a3ea224..40857b732c5a0ce076d159cdbe869a5c3ecd97c7 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -184,11 +184,9 @@ void display_startup()
 	glClear(GL_DEPTH_BUFFER_BIT);
 }
 
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Update Camera");
-
 void display_update_camera()
 {
-	LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA);
+    LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Camera");
 	// TODO: cut draw distance down if customizing avatar?
 	// TODO: cut draw distance on per-parcel basis?
 
@@ -246,32 +244,15 @@ void display_stats()
     }
 }
 
-static LLTrace::BlockTimerStatHandle FTM_PICK("Picking");
-static LLTrace::BlockTimerStatHandle FTM_RENDER("Render");
-static LLTrace::BlockTimerStatHandle FTM_RENDER_HUD("Render HUD");
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_SKY("Update Sky");
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_DYNAMIC_TEXTURES("Update Dynamic Textures");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE("Update Images");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_CLASS("Class");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_BUMP("Image Update Bump");
-static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_LIST("List");
-static LLTrace::BlockTimerStatHandle FTM_MATERIALS_FLUSH("GLTF Materials Cleanup");
-static LLTrace::BlockTimerStatHandle FTM_RESIZE_WINDOW("Resize Window");
-static LLTrace::BlockTimerStatHandle FTM_HUD_UPDATE("HUD Update");
-static LLTrace::BlockTimerStatHandle FTM_DISPLAY_UPDATE_GEOM("Update Geom");
-static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UNBIND("Texture Unbind");
-static LLTrace::BlockTimerStatHandle FTM_TELEPORT_DISPLAY("Teleport Display");
-static LLTrace::BlockTimerStatHandle FTM_EEP_UPDATE("Env Update");
-
 // Paint the display!
 void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 {
-	LL_RECORD_BLOCK_TIME(FTM_RENDER);
+    LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render");
 
 	if (gWindowResized)
 	{ //skip render on frames where window has been resized
 		LL_DEBUGS("Window") << "Resizing window" << LL_ENDL;
-		LL_RECORD_BLOCK_TIME(FTM_RESIZE_WINDOW);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Resize Window");
 		gGL.flush();
 		glClear(GL_COLOR_BUFFER_BIT);
 		gViewerWindow->getWindow()->swapBuffers();
@@ -293,11 +274,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		for_snapshot = FALSE;
 	}
 
-	if (LLPipeline::sRenderFrameTest)
-	{
-		send_agent_pause();
-	}
-
 	gSnapshot = for_snapshot;
 
 	LLGLSDefault gls_default;
@@ -342,8 +318,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 	gViewerWindow->checkSettings();
 	
 	{
-		LL_RECORD_BLOCK_TIME(FTM_PICK);
-		LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
+        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Picking");
 		gViewerWindow->performPick();
 	}
 	
@@ -421,7 +396,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 
 	if (gTeleportDisplay)
 	{
-		LL_RECORD_BLOCK_TIME(FTM_TELEPORT_DISPLAY);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Teleport Display");
 		LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
 		static LLCachedControl<F32> teleport_arrival_delay(gSavedSettings, "TeleportArrivalDelay");
 		static LLCachedControl<F32> teleport_local_delay(gSavedSettings, "TeleportLocalDelay");
@@ -633,7 +608,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
 	{
 		LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
-		LL_RECORD_BLOCK_TIME(FTM_UPDATE_DYNAMIC_TEXTURES);
+        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Dynamic Textures");
 		if (LLViewerDynamicTexture::updateAllInstances())
 		{
 			gGL.setColorMask(true, true);
@@ -664,21 +639,21 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		stop_glerror();
 				
 		{
-			LL_RECORD_BLOCK_TIME(FTM_EEP_UPDATE);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Env Update");
             // update all the sky/atmospheric/water settings
             LLEnvironment::instance().update(LLViewerCamera::getInstance());
 		}
 
 		// *TODO: merge these two methods
 		{
-			LL_RECORD_BLOCK_TIME(FTM_HUD_UPDATE);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("HUD Update");
 			LLHUDManager::getInstance()->updateEffects();
 			LLHUDObject::updateAll();
 			stop_glerror();
 		}
 
 		{
-			LL_RECORD_BLOCK_TIME(FTM_DISPLAY_UPDATE_GEOM);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Geom");
 			const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds.value(); // 50 ms/second update time
 			gPipeline.createObjects(max_geom_update_time);
 			gPipeline.processPartitionQ();
@@ -789,27 +764,27 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
 		
 		{
-			LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE);
+            LL_PROFILE_ZONE_NAMED("Update Images");
 			
 			{
-				LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_CLASS);
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Class");
 				LLViewerTexture::updateClass();
 			}
 
 			{
-				LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP);
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Image Update Bump");
 				gBumpImageList.updateImages();  // must be called before gTextureList version so that it's textures are thrown out first.
 			}
 
 			{
-				LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_LIST);
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("List");
 				F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds.value(); // 50 ms/second decode time
 				max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
 				gTextureList.updateImages(max_image_decode_time);
 			}
 
 			{
-				LL_RECORD_BLOCK_TIME(FTM_MATERIALS_FLUSH);
+                LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("GLTF Materials Cleanup");
 				//remove dead gltf materials
                 gGLTFMaterialList.flushMaterials();
 			}
@@ -988,7 +963,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		}
 
 		{
-			LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UNBIND);
+            LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Texture Unbind");
 			for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
 			{ //dummy cleanup of any currently bound textures
 				if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
@@ -1041,12 +1016,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 	
 	stop_glerror();
 
-	if (LLPipeline::sRenderFrameTest)
-	{
-		send_agent_resume();
-		LLPipeline::sRenderFrameTest = FALSE;
-	}
-
 	display_stats();
 				
 	LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
@@ -1063,7 +1032,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 // WIP simplified copy of display() that does minimal work
 void display_cube_face()
 {
-    LL_RECORD_BLOCK_TIME(FTM_RENDER);
+    LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render Cube Face");
     LL_PROFILE_GPU_ZONE("display cube face");
 
     llassert(!gSnapshot);
@@ -1451,11 +1420,9 @@ void render_ui(F32 zoom_factor, int subfield)
 	}
 }
 
-static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
-
 void swap()
 {
-	LL_RECORD_BLOCK_TIME(FTM_SWAP);
+    LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Swap");
     LL_PROFILE_GPU_ZONE("swap");
 	if (gDisplaySwapBuffers)
 	{
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ca96baee0a16e0a2327e5e11de5b5c2e8d143fc9..c214ea164d159582e2f82ab0a7e3c1b53be7ebd0 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1185,31 +1185,6 @@ class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t
 };
 
 
-
-////////////////
-// FRAME TEST //
-////////////////
-
-
-class LLAdvancedToggleFrameTest : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLPipeline::sRenderFrameTest = !(LLPipeline::sRenderFrameTest);
-		return true;
-	}
-};
-
-class LLAdvancedCheckFrameTest : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLPipeline::sRenderFrameTest;
-		return new_value;
-	}
-};
-
-
 ///////////////////////////
 // SELECTED TEXTURE INFO //
 // 
@@ -9438,8 +9413,6 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
 	view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
 	view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
-	view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest");
-	view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest");
 	view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
 	view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption");
 	view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption");
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 0be9abadbb2b9eaf8e8a4277b88056ff5f69810a..32fb7c13a9da030b68d167ed1fc0590cc5aed4f1 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -319,6 +319,8 @@ extern U32  gVisTested;
 
 void update_statistics()
 {
+    LL_PROFILE_ZONE_SCOPED;
+
 	gTotalWorldData += gVLManager.getTotalBytes();
 	gTotalObjectData += gObjectData;
 
@@ -350,16 +352,8 @@ void update_statistics()
 
 	typedef LLTrace::StatType<LLTrace::TimeBlockAccumulator>::instance_tracker_t stat_type_t;
 
-	F64Seconds idle_secs = last_frame_recording.getSum(*stat_type_t::getInstance("Idle"));
-	F64Seconds network_secs = last_frame_recording.getSum(*stat_type_t::getInstance("Network"));
-
 	record(LLStatViewer::FRAME_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Frame")));
-	record(LLStatViewer::UPDATE_STACKTIME, idle_secs - network_secs);
-	record(LLStatViewer::NETWORK_STACKTIME, network_secs);
-	record(LLStatViewer::IMAGE_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Update Images")));
-	record(LLStatViewer::REBUILD_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Sort Draw State")));
-	record(LLStatViewer::RENDER_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Render Geometry")));
-		
+
 	if (gAgent.getRegion() && isAgentAvatarValid())
 	{
 		LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 590f24d359e79c31f6b2faf13003d30226caa10d..c2e09b2882983347fdaa4013f19167ec61b0305f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1792,68 +1792,6 @@ void LLViewerFetchedTexture::processTextureStats()
 void LLViewerFetchedTexture::updateVirtualSize() 
 {	
     LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
-	if(!mMaxVirtualSizeResetCounter)
-	{
-		addTextureStats(0.f, FALSE);//reset
-	}
-
-    if (getBoostLevel() >= LLViewerTexture::BOOST_HIGH)
-    { //always load boosted textures at highest priority full res
-        addTextureStats(sMaxVirtualSize);
-        return;
-    }
-
-    if (sDesiredDiscardBias > 0.f)
-    {
-        // running out of video memory, don't hold onto high res textures in the background
-        mMaxVirtualSize = 0.f;
-    }
-
-	for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
-	{				
-		llassert(mNumFaces[ch] <= mFaceList[ch].size());
-
-		for(U32 i = 0; i < mNumFaces[ch]; i++)
-		{				
-			LLFace* facep = mFaceList[ch][i];
-		if( facep )
-		{
-			LLDrawable* drawable = facep->getDrawable();
-			if (drawable)
-			{
-				if(drawable->isRecentlyVisible())
-				{
-					if ((getBoostLevel() == LLViewerTexture::BOOST_NONE || getBoostLevel() == LLViewerTexture::BOOST_ALM)
-						&& drawable->getVObj()
-						&& drawable->getVObj()->isSelected())
-					{
-						setBoostLevel(LLViewerTexture::BOOST_SELECTED);
-					}
-					addTextureStats(facep->getVirtualSize());
-                    //drawable->getVObj()->setDebugText(llformat("%d:%d", (S32)sqrtf(facep->getVirtualSize()), (S32)sqrtf(getMaxVirtualSize())));
-				}
-                else
-                {
-                    //drawable->getVObj()->setDebugText("");
-                }
-			}
-		}
-	}
-	}
-	//reset whether or not a face was selected after 10 seconds
-	const F32 SELECTION_RESET_TIME = 10.f;
-
-	if (getBoostLevel() ==  LLViewerTexture::BOOST_SELECTED && 
-		gFrameTimeSeconds - mSelectedTime > SELECTION_RESET_TIME)
-	{
-		// Could have been BOOST_ALM, but if user was working with this texture, better keep it as NONE
-		setBoostLevel(LLViewerTexture::BOOST_NONE);
-	}
-
-	if(mMaxVirtualSizeResetCounter > 0)
-	{
-		mMaxVirtualSizeResetCounter--;
-	}
 	reorganizeFaceList();
 	reorganizeVolumeList();
 }
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 55a735e9060062b8d26146a75137ed99f5759928..338aac2cccdb0a2718586bdf09b5afad138fa5fa 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1048,8 +1048,8 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
     U32 update_count = 0;
     static const S32 MIN_UPDATE_COUNT = gSavedSettings.getS32("TextureFetchUpdateMinCount");       // default: 32
     // WIP -- dumb code here
-    //update MIN_UPDATE_COUNT or 10% of other textures, whichever is greater
-    update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/10);
+    //update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater
+    update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20);
     update_count = llmin(update_count, (U32) mUUIDMap.size());
     
     {
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index cf104aa89d9f0c86a05f83ad089249c8ba9f0355..41b57b8a6ba22df5e2bc6853bd7ab54fb5e86ef1 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5502,7 +5502,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		draw_vec[idx]->mTextureMatrix == tex_mat &&
 		draw_vec[idx]->mModelMatrix == model_mat &&
 		draw_vec[idx]->mShaderMask == shader_mask &&
-		draw_vec[idx]->mSelected == selected &&
         draw_vec[idx]->mAvatar == facep->mAvatar &&
         draw_vec[idx]->getSkinHash() == facep->getSkinHash())
 	{
@@ -5601,11 +5600,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		draw_info->mExtents[0] = facep->mExtents[0];
 		draw_info->mExtents[1] = facep->mExtents[1];
 
-		if (LLPipeline::sUseTriStrips)
-		{
-			draw_info->mDrawMode = LLRender::TRIANGLE_STRIP;
-		}
-
 		if (index < FACE_DO_NOT_BATCH_TEXTURES)
 		{ //initialize texture list for texture batching
 			draw_info->mTextureList.resize(index+1);
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index c7df343ad05ae16a2efff641cd332ca4990b0fe8..524fd4c49e5fd454d5adc60dbdf58a80d2eb007e 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -304,7 +304,7 @@ void LLVOWLSky::drawFsSky(void)
 
 	mFsSkyVerts->setBuffer(LLDrawPoolWLSky::ADV_ATMO_SKY_VERTEX_DATA_MASK);
 	mFsSkyVerts->drawRange(LLRender::TRIANGLES, 0, mFsSkyVerts->getNumVerts() - 1, mFsSkyVerts->getNumIndices(), 0);
-	gPipeline.addTrianglesDrawn(mFsSkyVerts->getNumIndices(), LLRender::TRIANGLES);
+	gPipeline.addTrianglesDrawn(mFsSkyVerts->getNumIndices());
 	LLVertexBuffer::unbind();
 }
 
@@ -331,7 +331,7 @@ void LLVOWLSky::drawDome(void)
 			LLRender::TRIANGLE_STRIP, 
 			0, strips_segment->getNumVerts()-1, strips_segment->getNumIndices(), 
 			0);
-		gPipeline.addTrianglesDrawn(strips_segment->getNumIndices(), LLRender::TRIANGLE_STRIP);
+		gPipeline.addTrianglesDrawn(strips_segment->getNumIndices());
 	}
 
 	LLVertexBuffer::unbind();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index dff84bda0e113f0481a2ab0eeb55ddd6a8fb872d..d2c079baa6ec49f95b0d179ba47a1535574596bc 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -313,7 +313,6 @@ bool	LLPipeline::sRenderTransparentWater = true;
 bool	LLPipeline::sRenderBump = true;
 bool	LLPipeline::sBakeSunlight = false;
 bool	LLPipeline::sNoAlpha = false;
-bool	LLPipeline::sUseTriStrips = true;
 bool	LLPipeline::sUseFarClip = true;
 bool	LLPipeline::sShadowRender = false;
 bool	LLPipeline::sRenderGlow = false;
@@ -323,7 +322,6 @@ bool	LLPipeline::sImpostorRender = false;
 bool	LLPipeline::sImpostorRenderAlphaDepthPass = false;
 bool	LLPipeline::sUnderWaterRender = false;
 bool	LLPipeline::sTextureBindTest = false;
-bool	LLPipeline::sRenderFrameTest = false;
 bool	LLPipeline::sRenderAttachedLights = true;
 bool	LLPipeline::sRenderAttachedParticles = true;
 bool	LLPipeline::sRenderDeferred = false;
@@ -406,7 +404,6 @@ void LLPipeline::init()
 	gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
 	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
     sRenderBump = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderObjectBump");
-	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
 	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
 	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
 	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
@@ -3716,31 +3713,40 @@ void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize)
             tex->addTextureStats(vsize);
         }
     }
-
-
 }
+
 void LLPipeline::touchTextures(LLDrawInfo* info)
 {
-    LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-
-    auto& mat = info->mGLTFMaterial;
-    if (mat.notNull())
-    {
-        touchTexture(mat->mBaseColorTexture, info->mVSize);
-        touchTexture(mat->mNormalTexture, info->mVSize);
-        touchTexture(mat->mMetallicRoughnessTexture, info->mVSize);
-        touchTexture(mat->mEmissiveTexture, info->mVSize);
-    }
-    else
+    if (--info->mTextureTimer == 0)
     {
-        for (int i = 0; i < info->mTextureList.size(); ++i)
+        LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+        // reset texture timer in a noisy fashion to avoid clumping of updates
+        const U32 MIN_WAIT_TIME = 8;
+        const U32 MAX_WAIT_TIME = 16;
+
+        info->mTextureTimer = ll_rand() % (MAX_WAIT_TIME - MIN_WAIT_TIME) + MIN_WAIT_TIME;
+
+        auto& mat = info->mGLTFMaterial;
+        if (mat.notNull())
         {
-            touchTexture(info->mTextureList[i], info->mTextureListVSize[i]);
+            touchTexture(mat->mBaseColorTexture, info->mVSize);
+            touchTexture(mat->mNormalTexture, info->mVSize);
+            touchTexture(mat->mMetallicRoughnessTexture, info->mVSize);
+            touchTexture(mat->mEmissiveTexture, info->mVSize);
         }
+        else
+        {
+            info->mTextureTimer += (U8) info->mTextureList.size();
 
-        touchTexture(info->mTexture, info->mVSize);
-        touchTexture(info->mSpecularMap, info->mVSize);
-        touchTexture(info->mNormalMap, info->mVSize);
+            for (int i = 0; i < info->mTextureList.size(); ++i)
+            {
+                touchTexture(info->mTextureList[i], info->mTextureListVSize[i]);
+            }
+
+            touchTexture(info->mTexture, info->mVSize);
+            touchTexture(info->mSpecularMap, info->mVSize);
+            touchTexture(info->mNormalMap, info->mVSize);
+        }
     }
 }
 
@@ -3829,7 +3835,7 @@ void LLPipeline::postSort(LLCamera& camera)
                 if (!sShadowRender && !sReflectionRender && !gCubeSnapshot)
                 {
                     touchTextures(info);
-                    addTrianglesDrawn(info->mCount, info->mDrawMode);
+                    addTrianglesDrawn(info->mCount);
                 }
             }
 		}
@@ -4831,28 +4837,19 @@ void LLPipeline::renderGeomShadow(LLCamera& camera)
 }
 
 
-void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
-{
-    LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-	assertInitialized();
-	S32 count = 0;
-	if (render_type == LLRender::TRIANGLE_STRIP)
-	{
-		count = index_count-2;
-	}
-	else
-	{
-		count = index_count/3;
-	}
+static U32 sIndicesDrawnCount = 0;
 
-	record(sStatBatchSize, count);
-	add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count));
+void LLPipeline::addTrianglesDrawn(S32 index_count)
+{
+    sIndicesDrawnCount += index_count;
+}
 
-	if (LLPipeline::sRenderFrameTest)
-	{
-		gViewerWindow->getWindow()->swapBuffers();
-		ms_sleep(16);
-	}
+void LLPipeline::recordTrianglesDrawn()
+{
+    assertInitialized();
+    U32 count = sIndicesDrawnCount / 3;
+    sIndicesDrawnCount = 0;
+    add(LLStatViewer::TRIANGLES_DRAWN, LLUnits::Triangles::fromValue(count));
 }
 
 void LLPipeline::renderPhysicsDisplay()
@@ -7385,7 +7382,6 @@ void LLPipeline::doResetVertexBuffers(bool forced)
 	updateRenderBump();
 	updateRenderDeferred();
 
-	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
 	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
 	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
 	LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
@@ -8246,6 +8242,9 @@ void LLPipeline::renderFinalize()
 
     LLGLState::checkStates();
     LLGLState::checkTextureChannels();
+
+    // flush calls made to "addTrianglesDrawn" so far to stats machinery
+    recordTrianglesDrawn();
 }
 
 void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index c61fbd8404f1bb3298a86231d6d5169e77b6bb71..5b068fc3863c501144102b3cef8801ce436ab9bc 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -354,8 +354,8 @@ class LLPipeline
     LLCullResult::sg_iterator beginRiggedAlphaGroups();
     LLCullResult::sg_iterator endRiggedAlphaGroups();
 	
-
-	void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES);
+	void addTrianglesDrawn(S32 index_count);
+    void recordTrianglesDrawn();
 
 	bool hasRenderDebugFeatureMask(const U32 mask) const	{ return bool(mRenderDebugFeatureMask & mask); }
 	bool hasRenderDebugMask(const U64 mask) const			{ return bool(mRenderDebugMask & mask); }
@@ -631,7 +631,6 @@ class LLPipeline
 	static bool				sRenderBump;
 	static bool				sBakeSunlight;
 	static bool				sNoAlpha;
-	static bool				sUseTriStrips;
 	static bool				sUseFarClip;
 	static bool				sShadowRender;
 	static bool				sDynamicLOD;
@@ -643,7 +642,6 @@ class LLPipeline
 	static bool				sUnderWaterRender;
 	static bool				sRenderGlow;
 	static bool				sTextureBindTest;
-	static bool				sRenderFrameTest;
 	static bool				sRenderAttachedLights;
 	static bool				sRenderAttachedParticles;
 	static bool				sRenderDeferred;
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index cb2f24334c0e2b0a021eff1a96638f9b6132902f..cb1dec6c6171f5e638055d32d3b2c87e303790d1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2744,15 +2744,6 @@ function="World.EnvPreset"
                  function="Advanced.TogglePeriodicSlowFrame"
                  parameter="points" />
             </menu_item_check>
-            <menu_item_check
-             label="Frame Test"
-             name="Frame Test">
-                <menu_item_check.on_check
-                 function="Advanced.CheckFrameTest"
-                 parameter="Frame Test" />
-                <menu_item_check.on_click
-                 function="Advanced.ToggleFrameTest" />
-            </menu_item_check>
           <menu_item_call
              label="Frame Profile"
              name="Frame Profile">