diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp
index 2072fda2bf..2ef5d5ecf1 100644
--- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp
+++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp
@@ -901,6 +901,22 @@ namespace glsl
 				"#define TEX2D_SHADOWPROJ_MS(index, coord4) TEX2D_SHADOW_MS(index, (coord4.xyz / coord4.w))\n"
 				"#define TEX2D_Z24X8_RGBA8_MS(index, coord2) process_texel(convert_z24x8_to_rgba8(ZS_READ_MS(index, coord2), texture_parameters[index].remap, TEX_FLAGS(index)), TEX_FLAGS(index))\n\n";
 
+				OS <<
+				R"(
+				vec3 compute2x2DownsampleWeights(const in float coord, const in float uv_step, const in float actual_step)
+				{
+					const float last_sample_point = max(coord - actual_step, 0.);
+					const float next_sample_point = min(coord + actual_step, 1.);
+					const float last_coord_step = floor(coord / uv_step) * uv_step;
+					const float next_coord_step = last_coord_step + uv_step;
+					const float next_next_coord_step = next_coord_step + uv_step;
+					const vec3 weights = vec3(next_coord_step - coord,
+								min(next_next_coord_step, next_sample_point) - next_coord_step,
+								max(next_next_coord_step, next_sample_point) - next_next_coord_step);
+					return weights / dot(weights, vec3(1));
+				}
+				)";
+
 				auto insert_msaa_sample_code = [&OS](const std::string_view& sampler_type)
 				{
 					OS <<
@@ -937,9 +953,9 @@ namespace glsl
 					"	}\n"
 					"\n"
 					"	// Fetch remaining samples\n"
-					"	const vec4 sample1 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(1, 0));\n"
-					"	const vec4 sample2 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(0, 1));\n"
-					"	const vec4 sample3 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(1, 1));\n"
+					"	const vec4 sample1 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(1, 0));\n"     // Bottom right
+					"	const vec4 sample2 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(0, 1));\n"     // Top left
+					"	const vec4 sample3 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(1, 1));\n"     // Top right
 					"\n"
 					"	vec4 a, b;\n"
 					"	float factor;\n"
@@ -947,13 +963,12 @@ namespace glsl
 					"	if (actual_step.x > uv_step.x)\n"
 					"	{\n"
 					"		// Downscale in X, centered\n"
-					"		const vec4 sample4 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(-1, 0));\n"
-					"		const vec4 sample5 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(-1, 1));\n"
+					"		const vec4 sample4 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(2, 0));\n"    // Further bottom right
+					"		const vec4 sample5 = texelFetch2DMS(tex, sample_count, icoords, index, ivec2(2, 1));\n"    // Further top right
+					"		const vec3 weights = compute2x2DownsampleWeights(normalized_coords.x, uv_step.x, actual_step.x);\n"
 					"\n"
-					"		factor = min(actual_step.x / uv_step.x, 2.0);\n"
-					"		const float half_factor = (factor - 1.) * 0.5;\n"
-					"		a = fma((sample1 + sample4), half_factor.xxxx, sample0) / factor;\n"
-					"		b = fma((sample3 + sample5), half_factor.xxxx, sample2) / factor;\n"
+					"		a = (sample0 * weights.x + sample1 * weights.y + sample4 * weights.z);\n"  // Weighted sum
+					"		b = (sample2 * weights.x + sample3 * weights.y + sample5 * weights.z);\n"  // Weighted sum
 					"	}\n"
 					"	else if (actual_step.x < uv_step.x)\n"
 					"	{\n"
@@ -972,8 +987,9 @@ namespace glsl
 					"	if (actual_step.y > uv_step.y)\n"
 					"	{\n"
 					"		// Downscale in Y\n"
-					"		factor = min(actual_step.y / uv_step.y, 2.0);\n"
-					"		return fma(b, (factor - 1).xxxx, a) / factor;\n"
+					"		const vec3 weights = compute2x2DownsampleWeights(normalized_coords.y, uv_step.y, actual_step.y);\n"
+					"		// We only have 2 rows computed for performance reasons, so combine rows 1 and 2\n"
+					"		return a * weights.x + b * (weights.y + weights.z);\n"
 					"	}\n"
 					"	else if (actual_step.y < uv_step.y)\n"
 					"	{\n"