diff --git a/autobuild.xml b/autobuild.xml
index bf52db0031a8f7e1e41c3b6fe7ec8b158efae95c..66ab2ef4ff85030378c089ad27ec815c33361951 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -142,11 +142,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>61df0d4054f53f7cb2a817d3d1509dae2cb7cfd9ce004c19dabdd80574c40a9b203d52d3a30f370aef77939219e42e7995dd1074ca1572fe9f5cca57424a7e36</string>
+              <string>fb238e2ae3b597d23b4cb8bf1c1f27b0fa64cdab2b9c5f39bcb28b622a3d8a72878110b55223f405c2b074bd5e2a87cf6a77a4379e9021943b09a5320e89697d</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/92/packages/generic/boost/1.83.0.2123/boost-1.83.0-darwin64-2123.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/92/packages/generic/boost/1.83.0.2149/boost-1.83.0-darwin64-2149.tar.zst</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -156,11 +156,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>8fa669bc9d7cda7942c8ab22847ef438ec6b91355a737f2291d6a1a122aef586b6504cdbfed03d13359c810023da1d43589994ab1efcdd017062916c121b6c7d</string>
+              <string>a649bf5b13ab53f3015362d5f735944bafed4654c55cc3339a6bd9aa3dfcc842cb170d9f2288669939b063ca5b86b6fbc4a99cd09bd5cbf6062c4057807bcf74</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/92/packages/generic/boost/1.83.0.2123/boost-1.83.0-linux64-2123.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/92/packages/generic/boost/1.83.0.2149/boost-1.83.0-linux64-2149.tar.zst</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -170,11 +170,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a59aed59bd8b8f24ff782e10a12408b0ad7f741ca1bb970007d1ec24bf1f913a12c72234bb554c59ae2d21a58169ef47f66bf1bab92e6c5c646c26dc870f41d0</string>
+              <string>8e5974aa5c767156049b55e9cce82758dda083e8b021f588881ec31fa5d0e4ca9c2e49e02d2e64d20ba34d32038fd17600d76f6a762c94b274e863b2812b9387</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/92/packages/generic/boost/1.83.0.2123/boost-1.83.0-windows64-2123.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/92/packages/generic/boost/1.83.0.2149/boost-1.83.0-windows64-2149.tar.zst</string>
             </map>
             <key>name</key>
             <string>windows64</string>
@@ -232,11 +232,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>4caf71582e656d3fde2f224e6c5db9026b606208f1a04a4920ec42eae0da5e9e26ccafd45fb77d59dce1a8c0a632c28fd3b124a708437e0d3279831827290af0</string>
+              <string>71e8e79741f35d33b216e1222825acb988f0feece1636899daa4ab287a58ca94dd0087f43123e32ba8cf8bb1d2f709b7b919f663de788f67a2bb5868b8ac5def</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/98/packages/generic/colladadom/2.3.0.2132/colladadom-2.3.0-darwin64-2132.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/98/packages/generic/colladadom/2.3.0.2150/colladadom-2.3.0-darwin64-2150.tar.zst</string>
             </map>
             <key>name</key>
             <string>darwin64</string>
@@ -246,11 +246,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a499b5527e26f6c35283142f74ff3a9a7754a8af1921f633b965a06b1ae21d274d12b982e51c9d14da1725e833b31868f5f1d0be825ce2642eb06660b3f22bfd</string>
+              <string>b61d702956e5c61bac9c128d73bf5fad78f6aa8b93ff2e7f8832b690ffd413689f84ce45885068a482a9d67ae96671092065972f79e79e006fdfc80db9203313</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/98/packages/generic/colladadom/2.3.0.2132/colladadom-2.3.0-linux64-2132.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/98/packages/generic/colladadom/2.3.0.2150/colladadom-2.3.0-linux64-2150.tar.zst</string>
             </map>
             <key>name</key>
             <string>linux64</string>
@@ -260,11 +260,11 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>dc7db00b88d4f27ccb92cd85b23bdca86458c845151a25c93d8c9fb85a1540aee9ba6cdf18bc6d90b386bfd5ad108ad3b338c72321f9cc50754e7695bad96779</string>
+              <string>6fabb0b052f06c8e1bf05dfa0de610e7119634c508b7a834ab21cc2ed1fb3d35daeae76a6c8a41c3b17b481c16074ee9bc6349e5099d342c51cb63a211e809b2</string>
               <key>hash_algorithm</key>
               <string>blake2b</string>
               <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/98/packages/generic/colladadom/2.3.0.2132/colladadom-2.3.0-windows64-2132.tar.zst</string>
+              <string>https://git.alchemyviewer.org/api/v4/projects/98/packages/generic/colladadom/2.3.0.2150/colladadom-2.3.0-windows64-2150.tar.zst</string>
             </map>
             <key>name</key>
             <string>windows64</string>
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 1df1e48d6a8f8d98e1f344ccbb426777c370ef21..fa54d4de26b31963c4f5664c04dcbf4a51bfd8fb 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 boost::unordered_flat_map<U32, U32> sTextureAllocs;
+static boost::unordered_flat_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;
 }
 
@@ -2071,7 +2071,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)
 	{
@@ -2084,7 +2084,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)
 	{
@@ -2092,7 +2092,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 21d4280c87f6b3f12254a7337fd09e6115e7bb52..3ad0f27ffb03da482aecee602bfd40b808ce5799 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; }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index c8eaba64182f8d6ced4b73614494d8a2a225f4aa..46ce7d66526e4a6e04211770aed7a7d97d1275e8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -375,6 +375,12 @@ vec2 BRDF(float NoV, float roughness)
     return texture(brdfLut, vec2(NoV, roughness)).rg;
 }
 
+// Lagarde and de Rousiers 2014, "Moving Frostbite to PBR"
+float computeSpecularAO(float NoV, float ao, float roughness) 
+{
+    return clamp(pow(NoV + ao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ao, 0.0, 1.0);
+}
+
 // set colorDiffuse and colorSpec to the results of GLTF PBR style IBL
 vec3 pbrIbl(vec3 diffuseColor,
             vec3 specularColor,
@@ -386,16 +392,20 @@ vec3 pbrIbl(vec3 diffuseColor,
             out vec3 specContrib)
 {
     // retrieve a scale and bias to F0. See [1], Figure 3
-	vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough);
-	vec3 diffuseLight = irradiance;
-	vec3 specularLight = radiance;
+    vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough);
+    vec3 diffuseLight = irradiance;
+    vec3 specularLight = radiance;
     
-	vec3 diffuse = diffuseLight * diffuseColor;
-	vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
+    vec3 energy = mix(brdf.xxx, brdf.yyy, specularColor);
+
+    vec3 diffuse = diffuseLight * diffuseColor * (1.0 - energy);
+    vec3 specular = specularLight * energy;
+
+    specular *= computeSpecularAO(nv, ao, perceptualRough * perceptualRough) * (1.0 + specularColor * (1.0 / brdf.y - 1.0));
 
-    specContrib = specular * ao;
+    specContrib = specular;
 
-	return (diffuse + specular) * ao;
+    return (diffuse * ao) + specular;
 }
 
 vec3 pbrIbl(vec3 diffuseColor,
diff --git a/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl
index e40d070268ef6223c861aa88e2fc15e998f1b312..df0d21b43231e597d32f5b713805457721456939 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl
@@ -129,7 +129,7 @@ vec2 BRDF(float NoV, float roughness)
 			float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
 			float G_Vis = (G * dotVH) / (dotNH * dotNV);
 			float Fc = pow(1.0 - dotVH, 5.0);
-			LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
+			LUT += vec2(Fc * G_Vis, G_Vis);
 		}
 	}
 	return LUT / float(NUM_SAMPLES);
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
index 4f79dd1ac5129a87f6afa97877d87e5c86b75c90..2411542c59810e9dca5cc632b698a79e358e1ac6 100644
--- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -266,7 +266,7 @@ void main()
 
     float nv = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0);
     vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0);
-    float f = 1.0-brdf.y; //1.0 - (brdf.x+brdf.y);
+    float f = 1.0-brdf.x; //1.0 - (brdf.x+brdf.y);
     f *= 0.9;
     f *= f;
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index bf7a55708c1107cd1784d9c13a678a2157a32a5c..493504e6502d8810453077c304bf0b40a28a657b 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -545,9 +545,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/pipeline.cpp b/indra/newview/pipeline.cpp
index 62895aee2a69403a2f806cdb081dca2fbe561520..8a887b645576277599ac69d4b14275cafe5a46f5 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -7283,21 +7283,6 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
 			static F32 transition_time = 1.f;
 
 			LLVector3 focus_point;
-
-			LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
-			if (obj && obj->mDrawable && obj->isSelected())
-			{ // focus on selected media object
-				S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
-				if (obj && obj->mDrawable)
-				{
-					LLFace* face = obj->mDrawable->getFace(face_idx);
-					if (face)
-					{
-						focus_point = face->getPositionAgent();
-					}
-				}
-			}
-
 			static LLVector3 last_focus_point{};
 			if (LLPipeline::RenderFocusPointLocked && !last_focus_point.isExactlyZero())
 			{
@@ -7305,9 +7290,23 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
 			}
 			else
 			{
+				LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+				if (obj && obj->mDrawable && obj->isSelected())
+				{ // focus on selected media object
+					S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+					if (obj && obj->mDrawable)
+					{
+						LLFace* face = obj->mDrawable->getFace(face_idx);
+						if (face)
+						{
+							focus_point = face->getPositionAgent();
+						}
+					}
+				}
+
 				if (focus_point.isExactlyZero())
 				{
-					if (LLViewerJoystick::getInstance()->getOverrideCamera())
+					if (LLViewerJoystick::getInstance()->getOverrideCamera() || LLPipeline::RenderFocusPointFollowsPointer)
 					{ // focus on point under cursor
 						focus_point.set(gDebugRaycastIntersection.getF32ptr());
 					}