diff --git a/doc/contributions.txt b/doc/contributions.txt
index 20980fdacd106b58a8c40e5c84563a7fed91e454..a8deb9c2aeb05de1873bf57897478f8ba5921642 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -270,6 +270,7 @@ Beq Janus
 	SL-13583
 	SL-14766
 	SL-14927
+	SL-15709
 Beth Walcher
 Bezilon Kasei
 Biancaluce Robbiani
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index 8900419f9b3465e24935b773fc3cb7a1c2f70178..c1cfa51cfb8aacb4f9229c989aea99091a9b771e 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -30,7 +30,7 @@ else (LINUX)
         ${BOOST_FIBER_LIBRARY} 
         ${BOOST_CONTEXT_LIBRARY} 
         ${BOOST_THREAD_LIBRARY} 
-        ${BOOST_SYSTEM_LIBRARY} )
+        ${BOOST_SYSTEM_LIBRARY})
 endif (LINUX)
 
 set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a static library.")
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index f1b0506659526b7b1ebb3c26db3f5cf62975db52..28bf5d0c398169729ccb186facdc2b0b0cd9b297 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -201,6 +201,7 @@ set(llcommon_HEADER_FILES
     llmortician.h
     llnametable.h
     llpointer.h
+    llprofiler.h
     llpounceable.h
     llpredicate.h
     llpreprocessor.h
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index e5a913a6a99c56214fc7365b2c13957aae0a810b..45ac43910c3c5b55ddedf9bbede30a4c83ebc987 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -60,4 +60,6 @@
 #include "llerror.h"
 #include "llfile.h"
 
+#include "llprofiler.h" // must be before fast timer; needed due to LLThreads potentially needing access to tracy
+
 #endif
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index dfc63d08a2979203866b0cf6ff7647e66867853e..c7d5bb3761fffcccb961f19b3f264a5e7cf2e782 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -38,7 +38,10 @@
 #define LL_FAST_TIMER_ON 1
 #define LL_FASTTIMER_USE_RDTSC 1
 
+// NOTE: Also see llprofiler.h
+#if !defined(LL_PROFILER_CONFIGURATION) // defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER)
 #define LL_RECORD_BLOCK_TIME(timer_stat) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
+#endif // LL_PROFILER_CONFIGURATION
 
 namespace LLTrace
 {
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
new file mode 100644
index 0000000000000000000000000000000000000000..75954b9a7943dca58510c7016f25505f4cd7c812
--- /dev/null
+++ b/indra/llcommon/llprofiler.h
@@ -0,0 +1,64 @@
+/**
+ * @file llprofiler.h
+ * @brief Wrapper for Tracy and/or other profilers
+ *
+ * $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_PROFILER_H
+#define LL_PROFILER_H
+
+#define LL_PROFILER_CONFIG_NONE             0  // No profiling
+#define LL_PROFILER_CONFIG_FAST_TIMER       1  // Profiling on: Only Fast Timers
+#define LL_PROFILER_CONFIG_TRACY            2  // Profiling on: Only Tracy
+#define LL_PROFILER_CONFIG_TRACY_FAST_TIMER 3  // Profiling on: Fast Timers + Tracy
+
+#if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE)
+    #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
+        #define TRACY_ENABLE         1
+        #define TRACY_NO_BROADCAST   1
+        #define TRACY_ONLY_LOCALHOST 1
+        #define TRACY_ONLY_IPV4      1
+        #include "Tracy.hpp"
+    #endif
+
+    #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
+        #define LL_PROFILER_FRAME_END               FrameMark
+        #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name )
+        #define LL_RECORD_BLOCK_TIME(name)          ZoneNamedN( ___tracy_scoped_zone, #name, true );
+    #endif
+    #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER
+        #define LL_PROFILER_FRAME_END
+        #define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name)
+        #define LL_RECORD_BLOCK_TIME(name)                                                                  const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
+    #endif
+    #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
+        #define LL_PROFILER_FRAME_END               FrameMark
+        #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name )
+        #define LL_RECORD_BLOCK_TIME(name)          ZoneNamedN( ___tracy_scoped_zone, #timer_stat, true )   const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
+    #endif
+#else
+    #define LL_PROFILER_FRAME_END
+    #define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name)
+#endif // LL_PROFILER
+
+#endif // LL_PROFILER_H
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 6d531d842d83c0e091d652112a53ca9a46a5ef21..a8cc7504372d17b32cfea5d96de91ee49a79c5d1 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -135,6 +135,8 @@ void LLThread::threadRun()
     set_thread_name(-1, mName.c_str());
 #endif
 
+    LL_PROFILER_SET_THREAD_NAME( mName.c_str() );
+
     // this is the first point at which we're actually running in the new thread
     mID = currentID();
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 79f1cc0e8f4da91fe889b46337fe0346a99cac0f..94f0b31ecde99f01b93eb06b6e67cd6b621db5a7 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1667,6 +1667,8 @@ bool LLAppViewer::doFrame()
 		LL_INFOS() << "Exiting main_loop" << LL_ENDL;
 	}
 
+    LL_PROFILER_FRAME_END
+
 	return ! LLApp::isRunning();
 }
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 109dc93261329a50d590c2ad23ea3a15725b88e9..a590237440fbe43583cea8a4b8ac97f7c7292a25 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1259,7 +1259,7 @@ bool setup_hud_matrices(const LLRect& screen_region)
 
 void render_ui(F32 zoom_factor, int subfield)
 {
-    LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
+	LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
 
 	LLGLState::checkStates();
 	
@@ -1274,7 +1274,7 @@ void render_ui(F32 zoom_factor, int subfield)
 	
 	if(LLSceneMonitor::getInstance()->needsUpdate())
 	{
-        LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_SCENE_MON);
+		LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_SCENE_MON);
 		gGL.pushMatrix();
 		gViewerWindow->setup2DRender();
 		LLSceneMonitor::getInstance()->compare();
@@ -1282,55 +1282,64 @@ void render_ui(F32 zoom_factor, int subfield)
 		gGL.popMatrix();
 	}
 
-    // Finalize scene
-    gPipeline.renderFinalize();
+	// Finalize scene
+	gPipeline.renderFinalize();
 
-    LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
-    render_hud_elements();
-	render_hud_attachments();
-
-	LLGLSDefault gls_default;
-	LLGLSUIDefault gls_ui;
 	{
-		gPipeline.disableLights();
-	}
+		// SL-15709
+		// NOTE: Tracy only allows one ZoneScoped per function.
+		// Solutions are:
+		// 1. Use a new scope
+		// 2. Use named zones
+		// 3. Use transient zones
+		LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
+		render_hud_elements();
+		render_hud_attachments();
+
+		LLGLSDefault gls_default;
+		LLGLSUIDefault gls_ui;
+		{
+			gPipeline.disableLights();
+		}
 
-	{
-		gGL.color4f(1,1,1,1);
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
 		{
-			if (!gDisconnected)
+			gGL.color4f(1,1,1,1);
+			if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
 			{
-                LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D);
-				render_ui_3d();
+				if (!gDisconnected)
+				{
+					LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D);
+					render_ui_3d();
+					LLGLState::checkStates();
+				}
+				else
+				{
+					render_disconnected_background();
+				}
+
+				LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D);
+				render_ui_2d();
 				LLGLState::checkStates();
 			}
-			else
+			gGL.flush();
+
 			{
-				render_disconnected_background();
+				LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_DEBUG_TEXT);
+				gViewerWindow->setup2DRender();
+				gViewerWindow->updateDebugText();
+				gViewerWindow->drawDebugText();
 			}
 
-            LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D);
-			render_ui_2d();
-			LLGLState::checkStates();
+			LLVertexBuffer::unbind();
 		}
-		gGL.flush();
 
+		if (!gSnapshot)
 		{
-            LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_DEBUG_TEXT);
-			gViewerWindow->setup2DRender();
-			gViewerWindow->updateDebugText();
-			gViewerWindow->drawDebugText();
+			set_current_modelview(saved_view);
+			gGL.popMatrix();
 		}
 
-		LLVertexBuffer::unbind();
-	}
-
-	if (!gSnapshot)
-	{
-		set_current_modelview(saved_view);
-		gGL.popMatrix();
-	}
+	} // Tracy integration
 }
 
 static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index f0638005870b0f16bf0e239484acccf8a91c970c..f9b2285989b5d65252e27071637e9b02ea981008 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -6045,123 +6045,130 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 	if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY))
 	{
 		LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB);
-		LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers
+		{
+			// SL-15709 -- NOTE: Tracy only allows one ZoneScoped per function.
+			// Solutions are:
+			// 1. Use a new scope
+			// 2. Use named zones
+			// 3. Use transient zones
+			LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers
 
-		group->mBuilt = 1.f;
+			group->mBuilt = 1.f;
 		
-		S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ;
+			S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ;
 
-		const U32 MAX_BUFFER_COUNT = 4096;
-		LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT];
-		
-		U32 buffer_count = 0;
+			const U32 MAX_BUFFER_COUNT = 4096;
+			LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT];
 
-		for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
-		{
-			LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
+			U32 buffer_count = 0;
 
-			if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
+			for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
 			{
-				LLVOVolume* vobj = drawablep->getVOVolume();
-                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();
-
-				if (drawablep->isState(LLDrawable::ANIMATED_CHILD))
-				{
-					vobj->updateRelativeXform(true);
-				}
+				LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
 
-				LLVolume* volume = vobj->getVolume();
-				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
+				if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
 				{
-					LLFace* face = drawablep->getFace(i);
-					if (face)
+					LLVOVolume* vobj = drawablep->getVOVolume();
+					if (debugLoggingEnabled("AnimatedObjectsLinkset"))
 					{
-						LLVertexBuffer* buff = face->getVertexBuffer();
-						if (buff)
+						if (vobj->isAnimatedObject() && vobj->isRiggedMesh())
 						{
-							llassert(!face->isState(LLFace::RIGGED));
+							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;
 
-							if (!face->getGeometryVolume(*volume, face->getTEOffset(), 
-								vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()))
-							{ //something's gone wrong with the vertex buffer accounting, rebuild this group 
-								group->dirtyGeom();
-								gPipeline.markRebuild(group, TRUE);
-							}
+					vobj->preRebuild();
 
+					if (drawablep->isState(LLDrawable::ANIMATED_CHILD))
+					{
+						vobj->updateRelativeXform(true);
+					}
 
-							if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT)
+					LLVolume* volume = vobj->getVolume();
+					for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
+					{
+						LLFace* face = drawablep->getFace(i);
+						if (face)
+						{
+							LLVertexBuffer* buff = face->getVertexBuffer();
+							if (buff)
 							{
-								locked_buffer[buffer_count++] = buff;
+								llassert(!face->isState(LLFace::RIGGED));
+
+								if (!face->getGeometryVolume(*volume, face->getTEOffset(), 
+									vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()))
+								{ //something's gone wrong with the vertex buffer accounting, rebuild this group 
+									group->dirtyGeom();
+									gPipeline.markRebuild(group, TRUE);
+								}
+
+
+								if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT)
+								{
+									locked_buffer[buffer_count++] = buff;
+								}
 							}
 						}
 					}
+
+					if (drawablep->isState(LLDrawable::ANIMATED_CHILD))
+					{
+						vobj->updateRelativeXform();
+					}
+
+					drawablep->clearState(LLDrawable::REBUILD_ALL);
 				}
+			}
 
-				if (drawablep->isState(LLDrawable::ANIMATED_CHILD))
+			{
+				LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH);
+				for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter)
 				{
-					vobj->updateRelativeXform();
+					(*iter)->flush();
 				}
 
-				
-				drawablep->clearState(LLDrawable::REBUILD_ALL);
+				// don't forget alpha
+				if(group != NULL &&
+				   !group->mVertexBuffer.isNull() &&
+				   group->mVertexBuffer->isLocked())
+				{
+					group->mVertexBuffer->flush();
+				}
 			}
-		}
-		
-		{
-			LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH);
-			for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter)
-		{
-			(*iter)->flush();
-		}
-
-		// don't forget alpha
-		if(group != NULL && 
-		   !group->mVertexBuffer.isNull() && 
-		   group->mVertexBuffer->isLocked())
-		{
-			group->mVertexBuffer->flush();
-		}
-		}
 
-		//if not all buffers are unmapped
-		if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) 
-		{
-			LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; 
-			for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
+			//if not all buffers are unmapped
+			if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount)
 			{
-				LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
-				if(!drawablep)
-				{
-					continue;
-				}
-				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
+				LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ;
+				for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
 				{
-					LLFace* face = drawablep->getFace(i);
-					if (face)
+					LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
+					if(!drawablep)
+					{
+						continue;
+					}
+					for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
 					{
-						LLVertexBuffer* buff = face->getVertexBuffer();
-						if (buff && buff->isLocked())
+						LLFace* face = drawablep->getFace(i);
+						if (face)
 						{
-							buff->flush();
+							LLVertexBuffer* buff = face->getVertexBuffer();
+							if (buff && buff->isLocked())
+							{
+								buff->flush();
+							}
 						}
 					}
 				}
-			} 
+			}
+
+			group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
 		}
 
-		group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
-	}
+	} // Tracy integration
 
 //	llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO));
 }
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index cd1b9c7c694c7c38cc19571c080ee08f0b127e10..e7c2d4db397105bdd5c2ac3f3bdda78e68ac1f80 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -4564,92 +4564,99 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
 	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
 
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
+	{
+		// SL-15709 -- NOTE: Tracy only allows one ZoneScoped per function.
+		// Solutions are:
+		// 1. Use a new scope
+		// 2. Use named zones
+		// 3. Use transient zones
+		LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS);
 
-	LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS);
-
-	LLGLEnable cull(GL_CULL_FACE);
+		LLGLEnable cull(GL_CULL_FACE);
 
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (hasRenderType(poolp->getType()))
+		for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
 		{
-			poolp->prerender();
+			LLDrawPool *poolp = *iter;
+			if (hasRenderType(poolp->getType()))
+			{
+				poolp->prerender();
+			}
 		}
-	}
 
-	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
 
-	LLVertexBuffer::unbind();
+		LLVertexBuffer::unbind();
 
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
 
-	U32 cur_type = 0;
+		U32 cur_type = 0;
 
-	gGL.setColorMask(true, true);
+		gGL.setColorMask(true, true);
 	
-	pool_set_t::iterator iter1 = mPools.begin();
+		pool_set_t::iterator iter1 = mPools.begin();
 
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
+		while ( iter1 != mPools.end() )
+		{
+			LLDrawPool *poolp = *iter1;
 		
-		cur_type = poolp->getType();
+			cur_type = poolp->getType();
 
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
-		{
-			LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER);
+			pool_set_t::iterator iter2 = iter1;
+			if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
+			{
+				LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER);
 
-			gGLLastMatrix = NULL;
-			gGL.loadMatrix(gGLModelView);
+				gGLLastMatrix = NULL;
+				gGL.loadMatrix(gGLModelView);
 		
-			for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginDeferredPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
 				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
+					LLVertexBuffer::unbind();
+					poolp->beginDeferredPass(i);
+					for (iter2 = iter1; iter2 != mPools.end(); iter2++)
 					{
-						break;
+						LLDrawPool *p = *iter2;
+						if (p->getType() != cur_type)
+						{
+							break;
+						}
+
+						if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); }
 					}
-										
-					if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); }
-				}
-				poolp->endDeferredPass(i);
-				LLVertexBuffer::unbind();
+					poolp->endDeferredPass(i);
+					LLVertexBuffer::unbind();
 
-				if (gDebugGL || gDebugPipeline)
-				{
-					LLGLState::checkStates();
+					if (gDebugGL || gDebugPipeline)
+					{
+						LLGLState::checkStates();
+					}
 				}
 			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			else
 			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
+				// Skip all pools of this type
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
 				{
-					break;
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
 				}
 			}
+			iter1 = iter2;
+			stop_glerror();
 		}
-		iter1 = iter2;
-		stop_glerror();
-	}
 
-	gGLLastMatrix = NULL;
-    gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.loadMatrix(gGLModelView);
+		gGLLastMatrix = NULL;
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+		gGL.loadMatrix(gGLModelView);
 
-	gGL.setColorMask(true, false);
+		gGL.setColorMask(true, false);
+
+	} // Tracy ZoneScoped
 }
 
 void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)