Fix the tune vmaf mode performance regression

Bug: 558679217

Change-Id: I77669167e79cf8390d0fffc9a8f1edb834262d6a
diff --git a/av1/common/x86/convolve_2d_avx2.c b/av1/common/x86/convolve_2d_avx2.c
index e6d06ee..256c070 100644
--- a/av1/common/x86/convolve_2d_avx2.c
+++ b/av1/common/x86/convolve_2d_avx2.c
@@ -273,17 +273,6 @@
     filt[2] = _mm256_load_si256((__m256i const *)filt3_global_avx2);
     filt[3] = _mm256_load_si256((__m256i const *)filt4_global_avx2);
 
-    if (subpel_x_qn == 0 && subpel_y_qn == 0) {
-      for (i = 0; i < h; ++i) {
-        for (int j = 0; j < w; j += 8) {
-          _mm_storel_epi64(
-              (__m128i *)&dst[i * dst_stride + j],
-              _mm_loadl_epi64((const __m128i *)&src[i * src_stride + j]));
-        }
-      }
-      return;
-    }
-
     for (i = 0; i < (im_h - 1); i += 2) {
       const uint8_t *src_row0 = &src_ptr[i * src_stride];
       const uint8_t *src_row1 = &src_ptr[(i + 1) * src_stride];
diff --git a/test/av1_convolve_test.cc b/test/av1_convolve_test.cc
index 7697285..bbc8015 100644
--- a/test/av1_convolve_test.cc
+++ b/test/av1_convolve_test.cc
@@ -1365,10 +1365,82 @@
     printf("%d - %d %3dx%-3d:%7.2f/%7.2fus (%3.2f)\n", h_f, v_f, width, height,
            time1, time2, time1 / time2);
   }
+
+ public:
+  void VmafTest() {
+    if (GetParam().Block().Width() < 8 || GetParam().Block().Height() < 8) {
+      return;
+    }
+    TestConvolveVmaf();
+  }
+
+ private:
+  void TestConvolveVmaf() {
+    // 8-tap Gaussian blur filter used by tune=vmaf_with_preprocessing
+    // in av1/encoder/tune_vmaf.c.
+    static const int16_t kGaussFilter[8] = { 2, 8, 24, 60, 24, 8, 2, 0 };
+    const InterpFilterParams filter_params = { kGaussFilter, 8,
+                                               EIGHTTAP_REGULAR };
+    const int width = GetParam().Block().Width();
+    const int height = GetParam().Block().Height();
+    const uint8_t *input = FirstRandomInput8(GetParam());
+    const int input_stride = width;
+    const int im_h = height + filter_params.taps - 1;
+    const int fo_vert = filter_params.taps / 2 - 1;
+    const int fo_horiz = filter_params.taps / 2 - 1;
+    const int kOverread = 8;
+    const int max_input_offset = -fo_vert * input_stride +
+                                 (im_h - 1) * input_stride + width - 1 -
+                                 fo_horiz + filter_params.taps - 1 + kOverread;
+    ASAN_POISON_MEMORY_REGION(input + max_input_offset + 1, 16);
+    const int min_input_offset = -fo_vert * input_stride - fo_horiz;
+    ASAN_POISON_MEMORY_REGION(input + min_input_offset - 16, 16);
+
+    DECLARE_ALIGNED(32, uint8_t, reference[MAX_SB_SQUARE]);
+    ConvolveParams conv_params1 =
+        get_conv_params_no_round(0, 0, nullptr, 0, 0, 8);
+    av1_convolve_2d_sr_c(input, input_stride, reference, kOutputStride, width,
+                         height, &filter_params, &filter_params, 0, 0,
+                         &conv_params1);
+
+    DECLARE_ALIGNED(32, uint8_t, test[MAX_SB_SQUARE]);
+    const int max_dst_offset = height * kOutputStride;
+    ASAN_POISON_MEMORY_REGION(test + max_dst_offset,
+                              sizeof(test) - max_dst_offset);
+    ConvolveParams conv_params2 =
+        get_conv_params_no_round(0, 0, nullptr, 0, 0, 8);
+    GetParam().TestFunction()(input, input_stride, test, kOutputStride, width,
+                              height, &filter_params, &filter_params, 0, 0,
+                              &conv_params2);
+    ASAN_UNPOISON_MEMORY_REGION(test + max_dst_offset,
+                                sizeof(test) - max_dst_offset);
+    ASAN_UNPOISON_MEMORY_REGION(input + max_input_offset + 1, 16);
+    ASAN_UNPOISON_MEMORY_REGION(input + min_input_offset - 16, 16);
+
+    // 1. Verify optimized implementation matches reference C implementation.
+    AssertOutputBufferEq(reference, test, width, height);
+
+    // 2. Verify that the output was actually convolved/blurred and is not
+    // merely an unmodified copy of the input. In commit 3d57983, a bug returned
+    // early with a pixel copy whenever subpel_x_qn == 0 && subpel_y_qn == 0,
+    // causing the Gaussian blur in VMAF mode to be skipped and
+    // best_frame_unsharp_amount to collapse from 1.0 to 0.05.
+    int diff_count = 0;
+    for (int r = 0; r < height; ++r) {
+      for (int c = 0; c < width; ++c) {
+        if (test[r * kOutputStride + c] != input[r * input_stride + c]) {
+          ++diff_count;
+        }
+      }
+    }
+    EXPECT_GT(diff_count, 0);
+  }
 };
 
 TEST_P(AV1Convolve2DTest, RunTest) { RunTest(); }
 
+TEST_P(AV1Convolve2DTest, VmafPreprocessing) { VmafTest(); }
+
 TEST_P(AV1Convolve2DTest, DISABLED_SpeedTest) { SpeedTest(); }
 
 INSTANTIATE_TEST_SUITE_P(C, AV1Convolve2DTest,
@@ -1613,10 +1685,59 @@
     printf("%d - %d %3dx%-3d:%7.2f/%7.2fus (%3.2f)\n", h_f, v_f, width, height,
            time1, time2, time1 / time2);
   }
+
+ public:
+  void VmafTest() {
+    if (GetParam().Block().Width() < 8 || GetParam().Block().Height() < 8) {
+      return;
+    }
+    TestConvolveVmaf();
+  }
+
+ private:
+  void TestConvolveVmaf() {
+    static const int16_t kGaussFilter[8] = { 2, 8, 24, 60, 24, 8, 2, 0 };
+    const InterpFilterParams filter_params = { kGaussFilter, 8,
+                                               EIGHTTAP_REGULAR };
+    const int width = GetParam().Block().Width();
+    const int height = GetParam().Block().Height();
+    const int bit_depth = GetParam().BitDepth();
+    const uint16_t *input = FirstRandomInput16(GetParam());
+    DECLARE_ALIGNED(32, uint16_t, reference[MAX_SB_SQUARE]);
+    ConvolveParams conv_params1 =
+        get_conv_params_no_round(0, 0, nullptr, 0, 0, bit_depth);
+    av1_highbd_convolve_2d_sr_c(input, width, reference, kOutputStride, width,
+                                height, &filter_params, &filter_params, 0, 0,
+                                &conv_params1, bit_depth);
+
+    DECLARE_ALIGNED(32, uint16_t, test[MAX_SB_SQUARE]);
+    ConvolveParams conv_params2 =
+        get_conv_params_no_round(0, 0, nullptr, 0, 0, bit_depth);
+    GetParam().TestFunction()(input, width, test, kOutputStride, width, height,
+                              &filter_params, &filter_params, 0, 0,
+                              &conv_params2, bit_depth);
+
+    // 1. Verify optimized implementation matches reference C implementation.
+    AssertOutputBufferEq(reference, test, width, height);
+
+    // 2. Verify that the output was actually convolved/blurred and is not
+    // merely an unmodified copy of the input.
+    int diff_count = 0;
+    for (int r = 0; r < height; ++r) {
+      for (int c = 0; c < width; ++c) {
+        if (test[r * kOutputStride + c] != input[r * width + c]) {
+          ++diff_count;
+        }
+      }
+    }
+    EXPECT_GT(diff_count, 0);
+  }
 };
 
 TEST_P(AV1Convolve2DHighbdTest, RunTest) { RunTest(); }
 
+TEST_P(AV1Convolve2DHighbdTest, VmafPreprocessing) { VmafTest(); }
+
 TEST_P(AV1Convolve2DHighbdTest, DISABLED_SpeedTest) { SpeedTest(); }
 
 INSTANTIATE_TEST_SUITE_P(C, AV1Convolve2DHighbdTest,