diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 577b7e91200f40910a2da3fc0d21e582d1c4f5b4..1418ebe89061771a3a3cfef022b455949a48b1aa 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -471,6 +471,7 @@ LLPanelFace::LLPanelFace()
     USE_TEXTURE = LLTrans::getString("use_texture");
     mCommitCallbackRegistrar.add("PanelFace.menuDoToSelected", boost::bind(&LLPanelFace::menuDoToSelected, this, _2));
     mEnableCallbackRegistrar.add("PanelFace.menuEnable", boost::bind(&LLPanelFace::menuEnableItem, this, _2));
+	mCommitCallbackRegistrar.add("BuildTool.SelectSameTexture", boost::bind(&LLPanelFace::onClickBtnSelectSameTexture, this, _1, _2));
 }
 
 LLPanelFace::~LLPanelFace()
@@ -1787,6 +1788,10 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
 		calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal());
         calcp->setVar(LLCalc::TEX_TRANSPARENCY, mCtrlColorTransp->getValue().asReal());
         calcp->setVar(LLCalc::TEX_GLOW, mCtrlGlow->getValue().asReal());
+
+		getChild<LLUICtrl>("btn_select_same_diff")->setEnabled(LLSelectMgr::getInstance()->getTEMode() && mTextureCtrl->getEnabled() && identical_diffuse);
+		getChild<LLUICtrl>("btn_select_same_norm")->setEnabled(LLSelectMgr::getInstance()->getTEMode() && mBumpyTextureCtrl->getEnabled() && identical_norm);
+		getChild<LLUICtrl>("btn_select_same_spec")->setEnabled(LLSelectMgr::getInstance()->getTEMode() && mShinyTextureCtrl->getEnabled() && identical_spec);
 	}
 	else
 	{
@@ -1992,6 +1997,8 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material,
         gltfCtrlTextureOffsetU->setEnabled(new_state);
         gltfCtrlTextureOffsetV->setEnabled(new_state);
 
+        getChild<LLUICtrl>("btn_select_same_pbr")->setEnabled(LLSelectMgr::getInstance()->getTEMode() && new_state && identical_pbr);
+
         // Control values will be set once per frame in
         // setMaterialOverridesFromSelection
         sMaterialOverrideSelection.setDirty();
@@ -2010,6 +2017,7 @@ void LLPanelFace::updateVisibilityGLTF(LLViewerObject* objectp /*= nullptr */)
     const bool show_pbr_render_material_id = show_pbr && (pbr_type == PBRTYPE_RENDER_MATERIAL_ID);
 
     getChildView("pbr_control")->setVisible(show_pbr_render_material_id);
+    getChildView("btn_select_same_pbr")->setVisible(show_pbr_render_material_id);
 
     getChildView("pbr_from_inventory")->setVisible(show_pbr_render_material_id);
     getChildView("edit_selected_pbr")->setVisible(show_pbr_render_material_id && !inventory_pending);
@@ -2909,6 +2917,7 @@ void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */)
 	getChildView("TexRot")->setVisible(show_texture);
 	getChildView("TexOffsetU")->setVisible(show_texture);
 	getChildView("TexOffsetV")->setVisible(show_texture);
+	getChild<LLUICtrl>("btn_select_same_diff")->setVisible(show_texture);
 
 	// Specular map controls
     mShinyTextureCtrl->setVisible(show_shininess);
@@ -2929,6 +2938,7 @@ void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */)
 	getChildView("shinyRot")->setVisible(show_shininess);
 	getChildView("shinyOffsetU")->setVisible(show_shininess);
 	getChildView("shinyOffsetV")->setVisible(show_shininess);
+	getChild<LLUICtrl>("btn_select_same_spec")->setVisible(show_shininess);
 
 	// Normal map controls
 	if (show_bumpiness)
@@ -2943,6 +2953,7 @@ void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */)
 	getChildView("bumpyRot")->setVisible(show_bumpiness);
 	getChildView("bumpyOffsetU")->setVisible(show_bumpiness);
 	getChildView("bumpyOffsetV")->setVisible(show_bumpiness);
+	getChild<LLUICtrl>("btn_select_same_norm")->setVisible(show_bumpiness);
 
     getChild<LLSpinCtrl>("rptctrl")->setVisible(show_material || show_media);
 
@@ -5389,3 +5400,86 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic
 	identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );
 }
 
+void LLPanelFace::onClickBtnSelectSameTexture(const LLUICtrl* ctrl, const LLSD& user_data)
+{
+	char channel = user_data.asStringRef()[0];
+
+	std::unordered_set<LLViewerObject*> objects;
+
+	// get a list of all linksets where at least one face is selected
+	for (auto iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
+		iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
+	{
+		objects.insert((*iter)->getObject()->getRootEdit());
+	}
+
+	// clean out the selection
+	LLSelectMgr::getInstance()->deselectAll();
+
+	// select all faces of all linksets that were found before
+	LLObjectSelectionHandle handle;
+	for(auto objectp : objects)
+	{
+		handle = LLSelectMgr::getInstance()->selectObjectAndFamily(objectp, true, false);
+	}
+
+	// grab the texture ID from the texture selector
+	LLTextureCtrl* texture_control = mTextureCtrl;
+	if (channel == 'n')
+	{
+		texture_control = mBumpyTextureCtrl;
+	}
+	else if (channel == 's')
+	{
+		texture_control = mShinyTextureCtrl;
+	}
+    else if (channel == 'p')
+    {
+        texture_control = getChild<LLTextureCtrl>("pbr_control");
+    }
+
+	LLUUID id = texture_control->getImageAssetID();
+
+	// go through all selected links in all selecrted linksets
+	for (auto iter = handle->begin(); iter != handle->end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* objectp = node->getObject();
+
+		U8 te_count = objectp->getNumTEs();
+
+		for (U8 i = 0; i < te_count; i++)
+		{
+			LLUUID image_id = objectp->getRenderMaterialID(i); // Always check PBR material to prevent selection of non-editable faces
+            if (image_id.isNull())
+            {
+                if (channel == 'd')
+                {
+                    image_id = objectp->getTEImage(i)->getID();
+                }
+                else
+                {
+                    const LLMaterialPtr mat = objectp->getTE(i)->getMaterialParams();
+                    if (mat.notNull())
+                    {
+                        if (channel == 'n')
+                        {
+                            image_id = mat->getNormalID();
+                        }
+                        else if (channel == 's')
+                        {
+                            image_id = mat->getSpecularID();
+                        }
+                    }
+                }
+            }
+
+			// deselect all faces that use a different texture UUID
+			if (image_id != id)
+			{
+				objectp->setTESelected(i, false);
+				node->selectTE(i, false);
+			}
+		}
+	}
+}
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 8ee76cd135ddeb501ef3b46cb00a28f8ecf37c5f..9f44e62047a83f120fc8d15fa72727ffd73d5b61 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -238,6 +238,8 @@ class LLPanelFace : public LLPanel
 	static void		onCommitPlanarAlign(		LLUICtrl* ctrl, void* userdata);
 	static void		onCommitRepeatsPerMeter(	LLUICtrl* ctrl, void* userinfo);
 
+	void onClickBtnSelectSameTexture(const LLUICtrl* ctrl, const LLSD& user_data);
+
     void            onCommitGLTFTextureScaleU(LLUICtrl* ctrl);
     void            onCommitGLTFTextureScaleV(LLUICtrl* ctrl);
     void            onCommitGLTFRotation(LLUICtrl* ctrl);
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index ec92701786e87f6b6bc93d580fd10e3f762a7e58..f35918167ced1bf69c45add1d756829b97d04803 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -251,18 +251,7 @@
                 name="clipboard_texture_params_btn"
                 tool_tip="Paste options"
                 width="22"/>
-            <check_box
-             control_name="SyncMaterialSettings"
-             follows="top|left"
-             height="47"
-             initial_value="false"
-             label="Lock repeat"
-             layout="topleft"
-             left="8"
-             name="checkbox_sync_settings"
-             tool_tip="Adjust all maps repeats simultaneously"
-             top_pad="19"
-             width="160" />
+
             <texture_picker
              can_apply_immediately="true"
              allow_no_texture="true"
@@ -273,7 +262,7 @@
              left="10"
              name="pbr_control"
              tool_tip="Click to choose a pbr material"
-             top_pad="5"
+             top_pad="71"
              width="64" />
             <button
              follows="left|top"
@@ -917,40 +906,6 @@
              max_val="1"
              name="shinyOffsetV"
              width="265" />
-            <check_box
-             follows="top|left"
-             height="16"
-             initial_value="false"
-             label="Align planar faces"
-             layout="topleft"
-             left="7"
-             name="checkbox planar align"
-             tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping."
-             top_delta="20"
-             width="260" />
-			<button
-             follows="left|top"
-             layout="topleft"
-			 left="9"
-			 top="231"
-			 height="20"
-			 label="Align"
-			 label_selected="Align current texture layers"
-			 name="button align textures"
-			 tool_tip="Align current texture layers"
-			 width="66" />
-            <web_browser
-             visible="false"
-             enabled="false"
-             border_visible="true"
-             bottom_delta="0"
-             follows="top|left"
-             left="0"
-             name="title_media"
-             width="4"
-             height="4"
-             start_url=""
-             decouple_texture_size="true" />
             <!-- BEGIN PBR Material texture transform parameters -->
             <spinner
              follows="left|top"
@@ -963,7 +918,7 @@
              min_val="-100"
              max_val="100"
              name="gltfTextureScaleU"
-             top_delta="34"
+             top_delta="-115"
              width="265" />
             <spinner
              follows="left|top"
@@ -1014,4 +969,106 @@
              name="gltfTextureOffsetV"
              width="265" />
             <!-- END PBR Material texture transform parameters -->
+            <check_box
+             follows="top|left"
+             height="16"
+             initial_value="false"
+             label="Align planar faces"
+             layout="topleft"
+             left="7"
+             name="checkbox planar align"
+             tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping."
+             top_pad="29"
+             width="203" />
+            <check_box
+             control_name="SyncMaterialSettings"
+             follows="top|left"
+             height="16"
+             initial_value="false"
+             label="Synchronize materials"
+             layout="topleft"
+             left="7"
+             top_pad="0"
+             name="checkbox_sync_settings"
+             tool_tip="Adjust all maps repeats simultaneously"
+             width="199" />
+            <button
+             layout="topleft"
+             follows="right|top"
+             height="23"
+             left_pad="0"
+             top_delta="-10"
+             label="Align"
+             name="button align textures"
+             tool_tip="Align current texture layers"
+             width="84" />
+            <web_browser
+             visible="false"
+             enabled="false"
+             border_visible="true"
+             bottom_delta="0"
+             follows="top|left"
+             left="0"
+             name="title_media"
+             width="4"
+             height="4"
+             start_url=""
+             decouple_texture_size="true" />
+            <button
+             enabled="true"
+             layout="topleft"
+             follows="right|top"
+             height="23"
+             left="15"
+             top="232"
+             label="Find All"
+             name="btn_select_same_diff"
+             tool_tip="Select all faces with the same diffuse texture as this one"
+             width="64">
+             <button.commit_callback
+               function="BuildTool.SelectSameTexture"
+               parameter="diffuse"/>
+            </button>
+            <button
+             enabled="true"
+             layout="topleft"
+             follows="right|top"
+             height="23"
+             left_delta="0"
+             label="Find All"
+             name="btn_select_same_norm"
+             tool_tip="Select all faces with the same normal map as this one"
+             width="64">
+             <button.commit_callback
+               function="BuildTool.SelectSameTexture"
+               parameter="normal"/>
+            </button>
+            <button
+             enabled="true"
+             layout="topleft"
+             follows="right|top"
+             height="23"
+             left_delta="0"
+             label="Find All"
+             name="btn_select_same_spec"
+             tool_tip="Select all faces with the same specular map as this one"
+             width="64">
+             <button.commit_callback
+               function="BuildTool.SelectSameTexture"
+               parameter="specular"/>
+            </button>
+            <button
+             enabled="true"
+             layout="topleft"
+             follows="right|top"
+             height="23"
+             left_delta="0"
+             label="Find All"
+             name="btn_select_same_pbr"
+             tool_tip="Select all faces with the same PBR material as this one"
+             width="64">
+             <button.commit_callback
+               function="BuildTool.SelectSameTexture"
+               parameter="pbr"/>
+            </button>
 </panel>