1 /*
2 * Copyright (c) 2017, 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 <stdint.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <tuple>
16
17 #include "config/aom_config.h"
18 #include "config/av1_rtcd.h"
19
20 #include "aom_ports/mem.h"
21 #include "av1/common/scan.h"
22 #include "av1/common/txb_common.h"
23 #include "gtest/gtest.h"
24 #include "test/acm_random.h"
25 #include "test/register_state_check.h"
26 #include "test/util.h"
27
28 namespace {
29 using libaom_test::ACMRandom;
30
31 using BuildCompDiffWtdMaskFunc = void (*)(uint8_t *mask,
32 DIFFWTD_MASK_TYPE mask_type,
33 const uint8_t *src0, int src0_stride,
34 const uint8_t *src1, int src1_stride,
35 int h, int w);
36
37 using BuildCompDiffwtdMaskDParam =
38 std::tuple<BLOCK_SIZE, BuildCompDiffWtdMaskFunc>;
39
40 #if HAVE_SSE4_1 || HAVE_AVX2 || HAVE_NEON
BuildParams(BuildCompDiffWtdMaskFunc filter)41 ::testing::internal::ParamGenerator<BuildCompDiffwtdMaskDParam> BuildParams(
42 BuildCompDiffWtdMaskFunc filter) {
43 return ::testing::Combine(::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL),
44 ::testing::Values(filter));
45 }
46 #endif
47
48 class BuildCompDiffwtdMaskTest
49 : public ::testing::TestWithParam<BuildCompDiffwtdMaskDParam> {
50 public:
BuildCompDiffwtdMaskTest()51 BuildCompDiffwtdMaskTest() : rnd_(ACMRandom::DeterministicSeed()) {}
52 ~BuildCompDiffwtdMaskTest() override = default;
53
54 protected:
RunTest(BuildCompDiffWtdMaskFunc test_impl,bool is_speed,const DIFFWTD_MASK_TYPE type)55 void RunTest(BuildCompDiffWtdMaskFunc test_impl, bool is_speed,
56 const DIFFWTD_MASK_TYPE type) {
57 const int sb_type = GET_PARAM(0);
58 const int width = block_size_wide[sb_type];
59 const int height = block_size_high[sb_type];
60 DECLARE_ALIGNED(16, uint8_t, mask_ref[MAX_SB_SQUARE]);
61 DECLARE_ALIGNED(16, uint8_t, mask_test[MAX_SB_SQUARE]);
62 DECLARE_ALIGNED(16, uint8_t, src0[MAX_SB_SQUARE]);
63 DECLARE_ALIGNED(16, uint8_t, src1[MAX_SB_SQUARE]);
64 for (int i = 0; i < width * height; i++) {
65 src0[i] = rnd_.Rand8();
66 src1[i] = rnd_.Rand8();
67 }
68 const int run_times = is_speed ? (10000000 / (width + height)) : 1;
69 aom_usec_timer timer;
70 aom_usec_timer_start(&timer);
71 for (int i = 0; i < run_times; ++i) {
72 av1_build_compound_diffwtd_mask_c(mask_ref, type, src0, width, src1,
73 width, height, width);
74 }
75 const double t1 = get_time_mark(&timer);
76 aom_usec_timer_start(&timer);
77 for (int i = 0; i < run_times; ++i) {
78 test_impl(mask_test, type, src0, width, src1, width, height, width);
79 }
80 const double t2 = get_time_mark(&timer);
81 if (is_speed) {
82 printf("mask %d %3dx%-3d:%7.2f/%7.2fns", type, width, height, t1, t2);
83 printf("(%3.2f)\n", t1 / t2);
84 }
85 for (int r = 0; r < height; ++r) {
86 for (int c = 0; c < width; ++c) {
87 ASSERT_EQ(mask_ref[c + r * width], mask_test[c + r * width])
88 << "[" << r << "," << c << "] " << run_times << " @ " << width
89 << "x" << height << " inv " << type;
90 }
91 }
92 }
93
94 private:
95 ACMRandom rnd_;
96 };
97 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BuildCompDiffwtdMaskTest);
98
TEST_P(BuildCompDiffwtdMaskTest,match)99 TEST_P(BuildCompDiffwtdMaskTest, match) {
100 RunTest(GET_PARAM(1), 0, DIFFWTD_38);
101 RunTest(GET_PARAM(1), 0, DIFFWTD_38_INV);
102 }
TEST_P(BuildCompDiffwtdMaskTest,DISABLED_Speed)103 TEST_P(BuildCompDiffwtdMaskTest, DISABLED_Speed) {
104 RunTest(GET_PARAM(1), 1, DIFFWTD_38);
105 RunTest(GET_PARAM(1), 1, DIFFWTD_38_INV);
106 }
107
108 #if HAVE_SSE4_1
109 INSTANTIATE_TEST_SUITE_P(SSE4_1, BuildCompDiffwtdMaskTest,
110 BuildParams(av1_build_compound_diffwtd_mask_sse4_1));
111 #endif
112
113 #if HAVE_AVX2
114 INSTANTIATE_TEST_SUITE_P(AVX2, BuildCompDiffwtdMaskTest,
115 BuildParams(av1_build_compound_diffwtd_mask_avx2));
116 #endif
117
118 #if HAVE_NEON
119 INSTANTIATE_TEST_SUITE_P(NEON, BuildCompDiffwtdMaskTest,
120 BuildParams(av1_build_compound_diffwtd_mask_neon));
121 #endif
122
123 #if CONFIG_AV1_HIGHBITDEPTH
124
125 using BuildCompDiffWtdMaskHighbdFunc =
126 void (*)(uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const uint8_t *src0,
127 int src0_stride, const uint8_t *src1, int src1_stride, int h,
128 int w, int bd);
129
130 using BuildCompDiffwtdMaskHighbdParam =
131 std::tuple<BLOCK_SIZE, int, BuildCompDiffWtdMaskHighbdFunc>;
132
133 #if HAVE_SSSE3 || HAVE_AVX2 || HAVE_NEON
134 ::testing::internal::ParamGenerator<BuildCompDiffwtdMaskHighbdParam>
BuildParamsHighbd(BuildCompDiffWtdMaskHighbdFunc filter)135 BuildParamsHighbd(BuildCompDiffWtdMaskHighbdFunc filter) {
136 return ::testing::Combine(::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL),
137 ::testing::Values(8, 10, 12),
138 ::testing::Values(filter));
139 }
140 #endif
141
142 class BuildCompDiffwtdMaskHighbdTest
143 : public ::testing::TestWithParam<BuildCompDiffwtdMaskHighbdParam> {
144 public:
BuildCompDiffwtdMaskHighbdTest()145 BuildCompDiffwtdMaskHighbdTest() : rnd_(ACMRandom::DeterministicSeed()) {}
146 ~BuildCompDiffwtdMaskHighbdTest() override = default;
147
148 protected:
RunTest(BuildCompDiffWtdMaskHighbdFunc test_impl,bool is_speed,const DIFFWTD_MASK_TYPE type)149 void RunTest(BuildCompDiffWtdMaskHighbdFunc test_impl, bool is_speed,
150 const DIFFWTD_MASK_TYPE type) {
151 const int sb_type = GET_PARAM(0);
152 const int bd = GET_PARAM(1);
153 const int width = block_size_wide[sb_type];
154 const int height = block_size_high[sb_type];
155 const int mask = (1 << bd) - 1;
156 DECLARE_ALIGNED(16, uint8_t, mask_ref[MAX_SB_SQUARE]);
157 DECLARE_ALIGNED(16, uint8_t, mask_test[MAX_SB_SQUARE]);
158 DECLARE_ALIGNED(16, uint16_t, src0[MAX_SB_SQUARE]);
159 DECLARE_ALIGNED(16, uint16_t, src1[MAX_SB_SQUARE]);
160 for (int i = 0; i < width * height; i++) {
161 src0[i] = rnd_.Rand16() & mask;
162 src1[i] = rnd_.Rand16() & mask;
163 }
164 const int run_times = is_speed ? (10000000 / (width + height)) : 1;
165 aom_usec_timer timer;
166
167 aom_usec_timer_start(&timer);
168 for (int i = 0; i < run_times; ++i) {
169 uint8_t *src0_8 = CONVERT_TO_BYTEPTR(src0);
170 uint8_t *src1_8 = CONVERT_TO_BYTEPTR(src1);
171 av1_build_compound_diffwtd_mask_highbd_c(
172 mask_ref, type, src0_8, width, src1_8, width, height, width, bd);
173 }
174 const double t1 = get_time_mark(&timer);
175
176 aom_usec_timer_start(&timer);
177 for (int i = 0; i < run_times; ++i) {
178 uint8_t *src0_8 = CONVERT_TO_BYTEPTR(src0);
179 uint8_t *src1_8 = CONVERT_TO_BYTEPTR(src1);
180 test_impl(mask_test, type, src0_8, width, src1_8, width, height, width,
181 bd);
182 }
183 const double t2 = get_time_mark(&timer);
184
185 if (is_speed) {
186 printf("mask %d %3dx%-3d:%7.2f/%7.2fns", type, width, height, t1, t2);
187 printf("(%3.2f)\n", t1 / t2);
188 }
189 for (int r = 0; r < height; ++r) {
190 for (int c = 0; c < width; ++c) {
191 ASSERT_EQ(mask_ref[c + r * width], mask_test[c + r * width])
192 << "[" << r << "," << c << "] " << run_times << " @ " << width
193 << "x" << height << " inv " << type;
194 }
195 }
196 }
197
198 private:
199 ACMRandom rnd_;
200 };
201 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BuildCompDiffwtdMaskHighbdTest);
202
TEST_P(BuildCompDiffwtdMaskHighbdTest,match)203 TEST_P(BuildCompDiffwtdMaskHighbdTest, match) {
204 RunTest(GET_PARAM(2), 0, DIFFWTD_38);
205 RunTest(GET_PARAM(2), 0, DIFFWTD_38_INV);
206 }
TEST_P(BuildCompDiffwtdMaskHighbdTest,DISABLED_Speed)207 TEST_P(BuildCompDiffwtdMaskHighbdTest, DISABLED_Speed) {
208 RunTest(GET_PARAM(2), 1, DIFFWTD_38);
209 RunTest(GET_PARAM(2), 1, DIFFWTD_38_INV);
210 }
211
212 #if HAVE_SSSE3
213 INSTANTIATE_TEST_SUITE_P(
214 SSSE3, BuildCompDiffwtdMaskHighbdTest,
215 BuildParamsHighbd(av1_build_compound_diffwtd_mask_highbd_ssse3));
216 #endif
217
218 #if HAVE_AVX2
219 INSTANTIATE_TEST_SUITE_P(
220 AVX2, BuildCompDiffwtdMaskHighbdTest,
221 BuildParamsHighbd(av1_build_compound_diffwtd_mask_highbd_avx2));
222 #endif
223
224 #if HAVE_NEON
225 INSTANTIATE_TEST_SUITE_P(
226 NEON, BuildCompDiffwtdMaskHighbdTest,
227 BuildParamsHighbd(av1_build_compound_diffwtd_mask_highbd_neon));
228 #endif
229 #endif // CONFIG_AV1_HIGHBITDEPTH
230
231 using BuildCompDiffWtdMaskD16Func = void (*)(
232 uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const CONV_BUF_TYPE *src0,
233 int src0_stride, const CONV_BUF_TYPE *src1, int src1_stride, int h, int w,
234 ConvolveParams *conv_params, int bd);
235
236 using BuildCompDiffwtdMaskD16Param =
237 std::tuple<int, BuildCompDiffWtdMaskD16Func, BLOCK_SIZE>;
238
239 #if HAVE_SSE4_1 || HAVE_AVX2 || HAVE_NEON
BuildParams(BuildCompDiffWtdMaskD16Func filter)240 ::testing::internal::ParamGenerator<BuildCompDiffwtdMaskD16Param> BuildParams(
241 BuildCompDiffWtdMaskD16Func filter) {
242 return ::testing::Combine(::testing::Range(8, 13, 2),
243 ::testing::Values(filter),
244 ::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
245 }
246 #endif
247
248 class BuildCompDiffwtdMaskD16Test
249 : public ::testing::TestWithParam<BuildCompDiffwtdMaskD16Param> {
250 public:
BuildCompDiffwtdMaskD16Test()251 BuildCompDiffwtdMaskD16Test() : rnd_(ACMRandom::DeterministicSeed()) {}
252 ~BuildCompDiffwtdMaskD16Test() override = default;
253
254 protected:
RunCheckOutput(BuildCompDiffWtdMaskD16Func test_impl)255 void RunCheckOutput(BuildCompDiffWtdMaskD16Func test_impl) {
256 const int block_idx = GET_PARAM(2);
257 const int bd = GET_PARAM(0);
258 const int width = block_size_wide[block_idx];
259 const int height = block_size_high[block_idx];
260 DECLARE_ALIGNED(16, uint8_t, mask_ref[2 * MAX_SB_SQUARE]);
261 DECLARE_ALIGNED(16, uint8_t, mask_test[2 * MAX_SB_SQUARE]);
262 DECLARE_ALIGNED(32, uint16_t, src0[MAX_SB_SQUARE]);
263 DECLARE_ALIGNED(32, uint16_t, src1[MAX_SB_SQUARE]);
264
265 ConvolveParams conv_params =
266 get_conv_params_no_round(0, 0, nullptr, 0, 1, bd);
267
268 const int in_precision =
269 bd + 2 * FILTER_BITS - conv_params.round_0 - conv_params.round_1 + 2;
270
271 for (int i = 0; i < MAX_SB_SQUARE; i++) {
272 src0[i] = rnd_.Rand16() & ((1 << in_precision) - 1);
273 src1[i] = rnd_.Rand16() & ((1 << in_precision) - 1);
274 }
275
276 for (int mask_type = 0; mask_type < DIFFWTD_MASK_TYPES; mask_type++) {
277 av1_build_compound_diffwtd_mask_d16_c(
278 mask_ref, (DIFFWTD_MASK_TYPE)mask_type, src0, width, src1, width,
279 height, width, &conv_params, bd);
280
281 test_impl(mask_test, (DIFFWTD_MASK_TYPE)mask_type, src0, width, src1,
282 width, height, width, &conv_params, bd);
283
284 for (int r = 0; r < height; ++r) {
285 for (int c = 0; c < width; ++c) {
286 ASSERT_EQ(mask_ref[c + r * width], mask_test[c + r * width])
287 << "Mismatch at unit tests for BuildCompDiffwtdMaskD16Test\n"
288 << " Pixel mismatch at index "
289 << "[" << r << "," << c << "] "
290 << " @ " << width << "x" << height << " inv " << mask_type;
291 }
292 }
293 }
294 }
295
RunSpeedTest(BuildCompDiffWtdMaskD16Func test_impl,DIFFWTD_MASK_TYPE mask_type)296 void RunSpeedTest(BuildCompDiffWtdMaskD16Func test_impl,
297 DIFFWTD_MASK_TYPE mask_type) {
298 const int block_idx = GET_PARAM(2);
299 const int bd = GET_PARAM(0);
300 const int width = block_size_wide[block_idx];
301 const int height = block_size_high[block_idx];
302 DECLARE_ALIGNED(16, uint8_t, mask[MAX_SB_SQUARE]);
303 DECLARE_ALIGNED(32, uint16_t, src0[MAX_SB_SQUARE]);
304 DECLARE_ALIGNED(32, uint16_t, src1[MAX_SB_SQUARE]);
305
306 ConvolveParams conv_params =
307 get_conv_params_no_round(0, 0, nullptr, 0, 1, bd);
308
309 const int in_precision =
310 bd + 2 * FILTER_BITS - conv_params.round_0 - conv_params.round_1 + 2;
311
312 for (int i = 0; i < MAX_SB_SQUARE; i++) {
313 src0[i] = rnd_.Rand16() & ((1 << in_precision) - 1);
314 src1[i] = rnd_.Rand16() & ((1 << in_precision) - 1);
315 }
316
317 const int num_loops = 10000000 / (width + height);
318 aom_usec_timer timer;
319 aom_usec_timer_start(&timer);
320
321 for (int i = 0; i < num_loops; ++i)
322 av1_build_compound_diffwtd_mask_d16_c(mask, mask_type, src0, width, src1,
323 width, height, width, &conv_params,
324 bd);
325
326 aom_usec_timer_mark(&timer);
327 const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
328
329 aom_usec_timer timer1;
330 aom_usec_timer_start(&timer1);
331
332 for (int i = 0; i < num_loops; ++i)
333 test_impl(mask, mask_type, src0, width, src1, width, height, width,
334 &conv_params, bd);
335
336 aom_usec_timer_mark(&timer1);
337 const int elapsed_time1 = static_cast<int>(aom_usec_timer_elapsed(&timer1));
338 printf("av1_build_compound_diffwtd_mask_d16 %3dx%-3d: %7.2f \n", width,
339 height, elapsed_time / double(elapsed_time1));
340 }
341
342 private:
343 ACMRandom rnd_;
344 }; // class BuildCompDiffwtdMaskD16Test
345 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BuildCompDiffwtdMaskD16Test);
346
TEST_P(BuildCompDiffwtdMaskD16Test,CheckOutput)347 TEST_P(BuildCompDiffwtdMaskD16Test, CheckOutput) {
348 RunCheckOutput(GET_PARAM(1));
349 }
350
TEST_P(BuildCompDiffwtdMaskD16Test,DISABLED_Speed)351 TEST_P(BuildCompDiffwtdMaskD16Test, DISABLED_Speed) {
352 RunSpeedTest(GET_PARAM(1), DIFFWTD_38);
353 RunSpeedTest(GET_PARAM(1), DIFFWTD_38_INV);
354 }
355
356 #if HAVE_SSE4_1
357 INSTANTIATE_TEST_SUITE_P(
358 SSE4_1, BuildCompDiffwtdMaskD16Test,
359 BuildParams(av1_build_compound_diffwtd_mask_d16_sse4_1));
360 #endif
361
362 #if HAVE_AVX2
363 INSTANTIATE_TEST_SUITE_P(AVX2, BuildCompDiffwtdMaskD16Test,
364 BuildParams(av1_build_compound_diffwtd_mask_d16_avx2));
365 #endif
366
367 #if HAVE_NEON
368 INSTANTIATE_TEST_SUITE_P(NEON, BuildCompDiffwtdMaskD16Test,
369 BuildParams(av1_build_compound_diffwtd_mask_d16_neon));
370 #endif
371
372 } // namespace
373