xref: /aosp_15_r20/external/libaom/test/subtract_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <cstdint>
13 #include <tuple>
14 
15 #include "gtest/gtest.h"
16 
17 #include "config/aom_config.h"
18 #include "config/aom_dsp_rtcd.h"
19 
20 #include "test/acm_random.h"
21 #include "test/register_state_check.h"
22 #include "test/util.h"
23 #include "av1/common/blockd.h"
24 #include "aom_mem/aom_mem.h"
25 #include "aom_ports/mem.h"
26 
27 typedef void (*SubtractFunc)(int rows, int cols, int16_t *diff_ptr,
28                              ptrdiff_t diff_stride, const uint8_t *src_ptr,
29                              ptrdiff_t src_stride, const uint8_t *pred_ptr,
30                              ptrdiff_t pred_stride);
31 
32 namespace {
33 
34 using std::get;
35 using std::make_tuple;
36 using std::tuple;
37 
38 using libaom_test::ACMRandom;
39 
40 // <BLOCK_SIZE, optimized subtract func, reference subtract func>
41 using Params = tuple<BLOCK_SIZE, SubtractFunc, SubtractFunc>;
42 
43 class AV1SubtractBlockTestBase : public ::testing::Test {
44  public:
AV1SubtractBlockTestBase(BLOCK_SIZE bs,int bit_depth,SubtractFunc func,SubtractFunc ref_func)45   AV1SubtractBlockTestBase(BLOCK_SIZE bs, int bit_depth, SubtractFunc func,
46                            SubtractFunc ref_func) {
47     block_width_ = block_size_wide[bs];
48     block_height_ = block_size_high[bs];
49     func_ = func;
50     ref_func_ = ref_func;
51     if (bit_depth == -1) {
52       hbd_ = false;
53       bit_depth_ = AOM_BITS_8;
54     } else {
55       hbd_ = true;
56       bit_depth_ = static_cast<aom_bit_depth_t>(bit_depth);
57     }
58   }
59 
SetUp()60   void SetUp() override {
61     rnd_.Reset(ACMRandom::DeterministicSeed());
62 
63     const size_t max_width = 128;
64     const size_t max_block_size = max_width * max_width;
65     if (hbd_) {
66       src_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
67           aom_memalign(16, max_block_size * sizeof(uint16_t))));
68       ASSERT_NE(src_, nullptr);
69       pred_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
70           aom_memalign(16, max_block_size * sizeof(uint16_t))));
71       ASSERT_NE(pred_, nullptr);
72     } else {
73       src_ = reinterpret_cast<uint8_t *>(
74           aom_memalign(16, max_block_size * sizeof(uint8_t)));
75       ASSERT_NE(src_, nullptr);
76       pred_ = reinterpret_cast<uint8_t *>(
77           aom_memalign(16, max_block_size * sizeof(uint8_t)));
78       ASSERT_NE(pred_, nullptr);
79     }
80     diff_ = reinterpret_cast<int16_t *>(
81         aom_memalign(32, max_block_size * sizeof(int16_t)));
82     ASSERT_NE(diff_, nullptr);
83   }
84 
TearDown()85   void TearDown() override {
86     if (hbd_) {
87       aom_free(CONVERT_TO_SHORTPTR(src_));
88       aom_free(CONVERT_TO_SHORTPTR(pred_));
89     } else {
90       aom_free(src_);
91       aom_free(pred_);
92     }
93     aom_free(diff_);
94   }
95 
96  protected:
97   void CheckResult();
98   void RunForSpeed();
99 
100  private:
101   void FillInputs();
102 
103   ACMRandom rnd_;
104   int block_height_;
105   int block_width_;
106   bool hbd_;
107   aom_bit_depth_t bit_depth_;
108   SubtractFunc func_;
109   SubtractFunc ref_func_;
110   uint8_t *src_;
111   uint8_t *pred_;
112   int16_t *diff_;
113 };
114 
FillInputs()115 void AV1SubtractBlockTestBase::FillInputs() {
116   const size_t max_width = 128;
117   const int max_block_size = max_width * max_width;
118   if (hbd_) {
119     const int mask = (1 << bit_depth_) - 1;
120     for (int i = 0; i < max_block_size; ++i) {
121       CONVERT_TO_SHORTPTR(src_)[i] = rnd_.Rand16() & mask;
122       CONVERT_TO_SHORTPTR(pred_)[i] = rnd_.Rand16() & mask;
123     }
124   } else {
125     if (src_ == nullptr) {
126       std::cerr << "gadfg" << std::endl;
127     }
128     for (int i = 0; i < max_block_size; ++i) {
129       src_[i] = rnd_.Rand8();
130       pred_[i] = rnd_.Rand8();
131     }
132   }
133 }
134 
CheckResult()135 void AV1SubtractBlockTestBase::CheckResult() {
136   const int test_num = 100;
137   int i;
138 
139   for (i = 0; i < test_num; ++i) {
140     FillInputs();
141 
142     func_(block_height_, block_width_, diff_, block_width_, src_, block_width_,
143           pred_, block_width_);
144 
145     if (hbd_)
146       for (int r = 0; r < block_height_; ++r) {
147         for (int c = 0; c < block_width_; ++c) {
148           EXPECT_EQ(diff_[r * block_width_ + c],
149                     (CONVERT_TO_SHORTPTR(src_)[r * block_width_ + c] -
150                      CONVERT_TO_SHORTPTR(pred_)[r * block_width_ + c]))
151               << "r = " << r << ", c = " << c << ", test: " << i;
152         }
153       }
154     else {
155       for (int r = 0; r < block_height_; ++r) {
156         for (int c = 0; c < block_width_; ++c) {
157           EXPECT_EQ(diff_[r * block_width_ + c],
158                     src_[r * block_width_ + c] - pred_[r * block_width_ + c])
159               << "r = " << r << ", c = " << c << ", test: " << i;
160         }
161       }
162     }
163   }
164 }
165 
RunForSpeed()166 void AV1SubtractBlockTestBase::RunForSpeed() {
167   const int test_num = 200000;
168   int i;
169 
170   if (ref_func_ == func_) GTEST_SKIP();
171 
172   FillInputs();
173 
174   aom_usec_timer ref_timer;
175   aom_usec_timer_start(&ref_timer);
176   for (i = 0; i < test_num; ++i) {
177     ref_func_(block_height_, block_width_, diff_, block_width_, src_,
178               block_width_, pred_, block_width_);
179   }
180   aom_usec_timer_mark(&ref_timer);
181   const int64_t ref_elapsed_time = aom_usec_timer_elapsed(&ref_timer);
182 
183   FillInputs();
184 
185   aom_usec_timer timer;
186   aom_usec_timer_start(&timer);
187   for (i = 0; i < test_num; ++i) {
188     func_(block_height_, block_width_, diff_, block_width_, src_, block_width_,
189           pred_, block_width_);
190   }
191   aom_usec_timer_mark(&timer);
192   const int64_t elapsed_time = aom_usec_timer_elapsed(&timer);
193 
194   printf(
195       "[%dx%d]: "
196       "ref_time=%6" PRId64 " \t simd_time=%6" PRId64
197       " \t "
198       "gain=%f \n",
199       block_width_, block_height_, ref_elapsed_time, elapsed_time,
200       static_cast<double>(ref_elapsed_time) /
201           static_cast<double>(elapsed_time));
202 }
203 
204 class AV1SubtractBlockTest : public ::testing::WithParamInterface<Params>,
205                              public AV1SubtractBlockTestBase {
206  public:
AV1SubtractBlockTest()207   AV1SubtractBlockTest()
208       : AV1SubtractBlockTestBase(GET_PARAM(0), -1, GET_PARAM(1), GET_PARAM(2)) {
209   }
210 };
211 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1SubtractBlockTest);
212 
TEST_P(AV1SubtractBlockTest,CheckResult)213 TEST_P(AV1SubtractBlockTest, CheckResult) { CheckResult(); }
TEST_P(AV1SubtractBlockTest,DISABLED_Speed)214 TEST_P(AV1SubtractBlockTest, DISABLED_Speed) { RunForSpeed(); }
215 
216 const BLOCK_SIZE kValidBlockSize[] = { BLOCK_4X4,    BLOCK_4X8,    BLOCK_8X4,
217                                        BLOCK_8X8,    BLOCK_8X16,   BLOCK_16X8,
218                                        BLOCK_16X16,  BLOCK_16X32,  BLOCK_32X16,
219                                        BLOCK_32X32,  BLOCK_32X64,  BLOCK_64X32,
220                                        BLOCK_64X64,  BLOCK_64X128, BLOCK_128X64,
221                                        BLOCK_128X128 };
222 
223 INSTANTIATE_TEST_SUITE_P(
224     C, AV1SubtractBlockTest,
225     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
226                        ::testing::Values(&aom_subtract_block_c),
227                        ::testing::Values(&aom_subtract_block_c)));
228 
229 #if HAVE_SSE2
230 INSTANTIATE_TEST_SUITE_P(
231     SSE2, AV1SubtractBlockTest,
232     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
233                        ::testing::Values(&aom_subtract_block_sse2),
234                        ::testing::Values(&aom_subtract_block_c)));
235 #endif
236 #if HAVE_AVX2
237 INSTANTIATE_TEST_SUITE_P(
238     AVX2, AV1SubtractBlockTest,
239     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
240                        ::testing::Values(&aom_subtract_block_avx2),
241                        ::testing::Values(&aom_subtract_block_c)));
242 
243 #endif
244 #if HAVE_NEON
245 INSTANTIATE_TEST_SUITE_P(
246     NEON, AV1SubtractBlockTest,
247     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
248                        ::testing::Values(&aom_subtract_block_neon),
249                        ::testing::Values(&aom_subtract_block_c)));
250 
251 #endif
252 
253 #if CONFIG_AV1_HIGHBITDEPTH
254 
255 // <BLOCK_SIZE, bit_depth, optimized subtract func, reference subtract func>
256 using ParamsHBD = tuple<BLOCK_SIZE, int, SubtractFunc, SubtractFunc>;
257 
258 class AV1HBDSubtractBlockTest : public ::testing::WithParamInterface<ParamsHBD>,
259                                 public AV1SubtractBlockTestBase {
260  public:
AV1HBDSubtractBlockTest()261   AV1HBDSubtractBlockTest()
262       : AV1SubtractBlockTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(2),
263                                  GET_PARAM(3)) {}
264 };
265 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1HBDSubtractBlockTest);
266 
267 INSTANTIATE_TEST_SUITE_P(
268     C, AV1HBDSubtractBlockTest,
269     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
270                        ::testing::Values(12),
271                        ::testing::Values(&aom_highbd_subtract_block_c),
272                        ::testing::Values(&aom_highbd_subtract_block_c)));
273 
274 #if HAVE_SSE2
275 INSTANTIATE_TEST_SUITE_P(
276     SSE2, AV1HBDSubtractBlockTest,
277     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
278                        ::testing::Values(12),
279                        ::testing::Values(&aom_highbd_subtract_block_sse2),
280                        ::testing::Values(&aom_highbd_subtract_block_c)));
281 #endif  // HAVE_SSE2
282 
283 #if HAVE_NEON
284 INSTANTIATE_TEST_SUITE_P(
285     NEON, AV1HBDSubtractBlockTest,
286     ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
287                        ::testing::Values(12),
288                        ::testing::Values(&aom_highbd_subtract_block_neon),
289                        ::testing::Values(&aom_highbd_subtract_block_c)));
290 #endif
291 #endif  // CONFIG_AV1_HIGHBITDEPTH
292 }  // namespace
293