diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index b77f98d65eaac5c37470abf6f82fc2e35a46dc13..c6fd824c4eed881c7aa05ff0f391a44267d60237 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -58,7 +58,7 @@ U32 wpo2(U32 i);
 
 // texture memory accounting (for OS X)
 static LLMutex sTexMemMutex;
-static std::unordered_map<U32, U32> sTextureAllocs;
+static std::unordered_map<U32, U64> sTextureAllocs;
 static U64 sTextureBytes = 0;
 
 // track a texture alloc on the currently bound texture.
@@ -67,7 +67,7 @@ static void alloc_tex_image(U32 width, U32 height, U32 pixformat)
 {
     U32 texUnit = gGL.getCurrentTexUnitIndex();
     U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture();
-    S32 size = LLImageGL::dataFormatBytes(pixformat, width, height);
+    U64 size = LLImageGL::dataFormatBytes(pixformat, width, height);
 
     llassert(size >= 0);
 
@@ -296,7 +296,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
 }
 
 //static
-S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
+S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
 {
     switch (dataformat)
     {
@@ -312,8 +312,8 @@ S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
     default:
         break;
     }
-	S32 bytes ((width*height*dataFormatBits(dataformat)+7)>>3);
-	S32 aligned = (bytes+3)&~3;
+	S64 bytes (((S64)width * (S64)height * (S64)dataFormatBits(dataformat)+7)>>3);
+	S64 aligned = (bytes+3)&~3;
 	return aligned;
 }
 
@@ -518,7 +518,7 @@ void LLImageGL::init(BOOL usemipmaps)
 	// so that it is obvious by visual inspection if we forgot to
 	// init a field.
 
-	mTextureMemory = (S32Bytes)0;
+	mTextureMemory = S64Bytes(0);
 	mLastBindTime = 0.f;
 
 	mPickMask = NULL;
@@ -1744,7 +1744,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
     }
 
     
-    mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel);
+    mTextureMemory = (S64Bytes)getMipBytes(mCurrentDiscardLevel);
     mTexelsInGLTexture = getWidth() * getHeight();
 
     // mark this as bound at this point, so we don't throw it out immediately
@@ -1938,9 +1938,9 @@ void LLImageGL::destroyGLTexture()
 
 	if (mTexName != 0)
 	{
-		if(mTextureMemory != S32Bytes(0))
+		if(mTextureMemory != S64Bytes(0))
 		{
-			mTextureMemory = (S32Bytes)0;
+			mTextureMemory = (S64Bytes)0;
 		}
 		
 		LLImageGL::deleteTextures(1, &mTexName);
@@ -2036,7 +2036,7 @@ S32 LLImageGL::getWidth(S32 discard_level) const
 	return width;
 }
 
-S32 LLImageGL::getBytes(S32 discard_level) const
+S64 LLImageGL::getBytes(S32 discard_level) const
 {
 	if (discard_level < 0)
 	{
@@ -2049,7 +2049,7 @@ S32 LLImageGL::getBytes(S32 discard_level) const
 	return dataFormatBytes(mFormatPrimary, w, h);
 }
 
-S32 LLImageGL::getMipBytes(S32 discard_level) const
+S64 LLImageGL::getMipBytes(S32 discard_level) const
 {
 	if (discard_level < 0)
 	{
@@ -2057,7 +2057,7 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const
 	}
 	S32 w = mWidth>>discard_level;
 	S32 h = mHeight>>discard_level;
-	S32 res = dataFormatBytes(mFormatPrimary, w, h);
+	S64 res = dataFormatBytes(mFormatPrimary, w, h);
 	if (mUseMipMaps)
 	{
 		while (w > 1 && h > 1)
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 243aeaea257867546144cdcbfb74db0c0c71e713..a9a6b93cb3d6843677498d1ccbdd80387bf9ebf1 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -65,7 +65,7 @@ class LLImageGL : public LLRefCount
 
 	// Size calculation
 	static S32 dataFormatBits(S32 dataformat);
-	static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
+	static S64 dataFormatBytes(S32 dataformat, S32 width, S32 height);
 	static S32 dataFormatComponents(S32 dataformat);
 
 	BOOL updateBindStats() const ;
@@ -145,8 +145,8 @@ class LLImageGL : public LLRefCount
 	S32	 getWidth(S32 discard_level = -1) const;
 	S32	 getHeight(S32 discard_level = -1) const;
 	U8	 getComponents() const { return mComponents; }
-	S32  getBytes(S32 discard_level = -1) const;
-	S32  getMipBytes(S32 discard_level = -1) const;
+	S64  getBytes(S32 discard_level = -1) const;
+	S64  getMipBytes(S32 discard_level = -1) const;
 	BOOL getBoundRecently() const;
 	BOOL isJustBound() const;
 	BOOL getHasExplicitFormat() const { return mHasExplicitFormat; }
@@ -208,7 +208,7 @@ class LLImageGL : public LLRefCount
 
 public:
 	// Various GL/Rendering options
-	S32Bytes mTextureMemory;
+	S64Bytes mTextureMemory;
 	mutable F32  mLastBindTime;	// last time this was bound, by discard level
 	
 private:
diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp
index 18be4fffda105fa9efdaad71601fabfe83cfcadd..f3133ecb37baf9ca2ebde536b501dfd0e3d0c960 100644
--- a/indra/newview/llfloaterenvironmentadjust.cpp
+++ b/indra/newview/llfloaterenvironmentadjust.cpp
@@ -495,10 +495,12 @@ void LLFloaterEnvironmentAdjust::updateGammaLabel()
     if (ambiance != 0.f)
     {
         childSetValue("scene_gamma_label", getString("hdr_string"));
+        getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setToolTip(getString("hdr_tooltip"));
     }
     else
     {
         childSetValue("scene_gamma_label", getString("brightness_string"));
+        getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setToolTip(std::string());
     }
 }
 
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index b6acba6558b90cb2e8ac14aa548fb61655323add..5fb4fb9b07a0737cb6d48782cb6bc1fafa3bd57c 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -925,6 +925,9 @@ void LLFloaterTools::onClose(bool app_quitting)
 	// hide the advanced object weights floater
 	LLFloaterReg::hideInstance("object_weights");
 
+    // hide gltf material editor
+    LLFloaterReg::hideInstance("live_material_editor");
+
 	// prepare content for next call
 	mPanelContents->clearContents();
 
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index a0c3fd9a28faa0aa1018ff8424246a2bddbdb43e..0897ed14c63ad0bc94f232125482724711fb390d 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -412,9 +412,6 @@ BOOL LLMaterialEditor::postBuild()
 
     if (mIsOverride)
     {
-        // Material override change success callback
-        LLGLTFMaterialList::addSelectionUpdateCallback(&LLMaterialEditor::updateLive);
-
         // Live editing needs a recovery mechanism on cancel
         mBaseColorTextureCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_BASE_COLOR_TEX_DIRTY));
         mMetallicTextureCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY));
@@ -542,12 +539,6 @@ void LLMaterialEditor::draw()
 {
     if (mIsOverride)
     {
-        bool selection_empty = LLSelectMgr::getInstance()->getSelection()->isEmpty();
-        if (selection_empty && mHasSelection)
-        {
-            mSelectionNeedsUpdate = true;
-        }
-
         if (mSelectionNeedsUpdate)
         {
             mSelectionNeedsUpdate = false;
@@ -1790,22 +1781,6 @@ void LLMaterialEditor::updateLive()
     mOverrideInProgress = false;
 }
 
-void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te)
-{
-    if (mOverrideObjectId != object_id
-        || mOverrideObjectTE != te)
-    {
-        // Ignore if waiting for override,
-        // if not waiting, mark selection dirty
-        mSelectionNeedsUpdate |= !mOverrideInProgress;
-        return;
-    }
-
-    // update for currently displayed object and face
-    mSelectionNeedsUpdate = true;
-    mOverrideInProgress = false;
-}
-
 void LLMaterialEditor::loadLive()
 {
     LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("live_material_editor");
@@ -2816,7 +2791,7 @@ class LLRenderMaterialOverrideFunctor : public LLSelectedNodeFunctor
             // something went wrong update selection
             LLMaterialEditor::updateLive();
         }
-        // else we will get updateLive(obj, id) from applied overrides
+        // else we will get updateLive() from panel face
     }
 
     bool getResult() { return mSuccess; }
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index b29db706f819c93a01f3d59582c0471b3f8a4256..1c40fcc348f29c1a8c60cf05f4ff95be09337a80 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -110,7 +110,6 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
     void onSelectionChanged(); // live overrides selection changes
 
     static void updateLive();
-    static void updateLive(const LLUUID &object_id, S32 te);
     static void loadLive();
 
     static bool canModifyObjectsMaterial();
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index 0a7a4763beb86ea051d3cd8b8840a487fabdb47d..839f25761a77112a85ea37dc49ccb5907c563836 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -342,10 +342,12 @@ void LLPanelSettingsSkyAtmosTab::updateGammaLabel(bool auto_adjust)
     if (ambiance != 0.f)
     {
         childSetValue("scene_gamma_label", getString("hdr_string"));
+        getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setToolTip(getString("hdr_tooltip"));
     }
     else
     {
         childSetValue("scene_gamma_label", getString("brightness_string"));
+        getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setToolTip(std::string());
     }
 
 }
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index e1f08915fa83e42286fb1fb2e933bec3e33e7ef6..cb28fb47708d896ae2e62fb74ef7334ddd06bb83 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -515,6 +515,7 @@ void LLPanelFace::draw()
     if (sMaterialOverrideSelection.update())
     {
         setMaterialOverridesFromSelection();
+        LLMaterialEditor::updateLive();
     }
 }
 
@@ -1056,6 +1057,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
         LLSelectedTEMaterial::getSpecularID(specmap_id, identical_spec);
 
         static S32 selected_te = -1;
+        static LLUUID prev_obj_id;
         if ((LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()) && 
             !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) 
         {
@@ -1070,7 +1072,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
                 }
             }
 
-            if (new_selection != selected_te)
+            if ((new_selection != selected_te)
+                || (prev_obj_id != objectp->getID()))
             {
                 bool te_has_media = objectp->getTE(new_selection) && objectp->getTE(new_selection)->hasMedia();
                 bool te_has_pbr = objectp->getRenderMaterialID(new_selection).notNull();
@@ -1088,6 +1091,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
                     mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
                 }
                 selected_te = new_selection;
+                prev_obj_id = objectp->getID();
             }
         }
 
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 7e399a6808351b1c30ed93b880790b532ce9a301..bbacec843beb7142bb6f2e0e374cf6de3d8018fa 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -2101,8 +2101,16 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item)
 		return mDropCallback(this, item);
 	}
 
-	// no callback installed, so just set the image ids and carry on.
-	setImageAssetID( item->getAssetUUID() );
+    // no callback installed, so just set the image ids and carry on.
+    LLUUID asset_id = item->getAssetUUID();
+
+    if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL && asset_id.isNull())
+    {
+        // If an inventory material has a null asset, consider it a valid blank material(gltf)
+        asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID;
+    }
+
+	setImageAssetID(asset_id);
 	mImageItemID = item->getUUID();
 	return TRUE;
 }
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 82b16d67bd62d1be2d00b79002f292b78f80799c..d52f0b68fad5cb3abe0013344620f22015ba96b9 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -2286,12 +2286,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         if (local_light_kill)
         {
             gDeferredSoftenWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
-            gDeferredSoftenWaterProgram.addPermutation("HAS_SSAO", "1");
         }
 
 		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
 			gDeferredSoftenWaterProgram.mShaderLevel = llmax(gDeferredSoftenWaterProgram.mShaderLevel, 2);
+            gDeferredSoftenWaterProgram.addPermutation("HAS_SSAO", "1");
 		}
 
 		success = gDeferredSoftenWaterProgram.createShader(NULL, NULL);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 9fc092d4b98e199be52a6836168f5daf7cff9db7..9336d9955543a230d71c6c81f7ebe09341f3a4b7 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -534,9 +534,12 @@ void LLViewerTexture::updateClass()
 
     static LLCachedControl<U32> max_vram_budget(gSavedSettings, "RenderMaxVRAMBudget", 0);
 
+	F64 texture_bytes_alloc = LLImageGL::getTextureBytesAllocated() / 1024.0 / 512.0;
+	F64 vertex_bytes_alloc = LLVertexBuffer::getBytesAllocated() / 1024.0 / 512.0;
+
     // get an estimate of how much video memory we're using 
     // NOTE: our metrics miss about half the vram we use, so this biases high but turns out to typically be within 5% of the real number
-    F32 used = (LLImageGL::getTextureBytesAllocated() + LLVertexBuffer::getBytesAllocated()) / 1024 / 512;
+	F32 used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc);
     
     F32 budget = max_vram_budget == 0 ? gGLManager.mVRAM : max_vram_budget;
 
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 518a83f846a393ffeb6e0b8af59c69948293fbb2..91a1dffcb5facdcb5d2d041447534cdf180b9683 100644
--- a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
+++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
@@ -12,6 +12,7 @@
          can_resize="false">
   <string name="hdr_string">HDR Scale:</string>
   <string name="brightness_string">Brightness:</string>
+  <string name="hdr_tooltip">Intensity of lightning effects such as realistically bright skies and dynamic exposure. 1.0 is the default, 0 is off, values between 0 and 1 are mixing Ambient with HDR.</string>
     <layout_stack name="outer_stack"
                   width="845"
                   height="275"
@@ -263,6 +264,7 @@
                           min_val="0"
                           max_val="10"
                           name="probe_ambiance"
+                          tool_tip="Intensity of environment based indirect lighting. At zero HDR scale becomes Brightness"
                           top_pad="5"
                           width="185"
                           can_edit_text="true"/>
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 2d79bc74ab8a963f2ac22f5166d694ba6e70de4b..da82c95c8384fbddb98c8df85c734b9dbe98a3c5 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
@@ -9,6 +9,7 @@
         top="0">
   <string name="hdr_string">HDR Scale:</string>
   <string name="brightness_string">Brightness:</string>
+  <string name="hdr_tooltip">Intensity of lightning effects such as realistically bright skies and dynamic exposure. 1.0 is the default, 0 is off, values between 0 and 1 are mixing Ambient with HDR.</string>
     <layout_stack
             name="main_ls"
             follows="all"
@@ -332,6 +333,7 @@
                           min_val="0"
                           max_val="10"
                           name="probe_ambiance"
+                          tool_tip="Intensity of environment based indirect lighting. At zero HDR scale becomes Brightness"
                           top_delta="20"
                           width="219"
                           can_edit_text="true"/>