Line data Source code
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 : #include <immintrin.h>
12 : #include <string.h>
13 :
14 : #include "./aom_dsp_rtcd.h"
15 : #include "aom_dsp/x86/convolve.h"
16 :
17 : // -----------------------------------------------------------------------------
18 : // Copy and average
19 :
20 0 : void aom_highbd_convolve_copy_avx2(const uint8_t *src8, ptrdiff_t src_stride,
21 : uint8_t *dst8, ptrdiff_t dst_stride,
22 : const int16_t *filter_x, int filter_x_stride,
23 : const int16_t *filter_y, int filter_y_stride,
24 : int width, int h, int bd) {
25 0 : const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
26 0 : uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
27 : (void)filter_x;
28 : (void)filter_y;
29 : (void)filter_x_stride;
30 : (void)filter_y_stride;
31 : (void)bd;
32 :
33 0 : assert(width % 4 == 0);
34 0 : if (width > 32) { // width = 64
35 : do {
36 0 : const __m256i p0 = _mm256_loadu_si256((const __m256i *)src);
37 0 : const __m256i p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
38 0 : const __m256i p2 = _mm256_loadu_si256((const __m256i *)(src + 32));
39 0 : const __m256i p3 = _mm256_loadu_si256((const __m256i *)(src + 48));
40 0 : src += src_stride;
41 : _mm256_storeu_si256((__m256i *)dst, p0);
42 0 : _mm256_storeu_si256((__m256i *)(dst + 16), p1);
43 0 : _mm256_storeu_si256((__m256i *)(dst + 32), p2);
44 0 : _mm256_storeu_si256((__m256i *)(dst + 48), p3);
45 0 : dst += dst_stride;
46 0 : h--;
47 0 : } while (h > 0);
48 0 : } else if (width > 16) { // width = 32
49 : do {
50 0 : const __m256i p0 = _mm256_loadu_si256((const __m256i *)src);
51 0 : const __m256i p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
52 0 : src += src_stride;
53 : _mm256_storeu_si256((__m256i *)dst, p0);
54 0 : _mm256_storeu_si256((__m256i *)(dst + 16), p1);
55 0 : dst += dst_stride;
56 0 : h--;
57 0 : } while (h > 0);
58 0 : } else if (width > 8) { // width = 16
59 : __m256i p0, p1;
60 : do {
61 0 : p0 = _mm256_loadu_si256((const __m256i *)src);
62 0 : src += src_stride;
63 0 : p1 = _mm256_loadu_si256((const __m256i *)src);
64 0 : src += src_stride;
65 :
66 : _mm256_storeu_si256((__m256i *)dst, p0);
67 0 : dst += dst_stride;
68 : _mm256_storeu_si256((__m256i *)dst, p1);
69 0 : dst += dst_stride;
70 0 : h -= 2;
71 0 : } while (h > 0);
72 0 : } else if (width > 4) { // width = 8
73 : __m128i p0, p1;
74 : do {
75 0 : p0 = _mm_loadu_si128((const __m128i *)src);
76 0 : src += src_stride;
77 0 : p1 = _mm_loadu_si128((const __m128i *)src);
78 0 : src += src_stride;
79 :
80 : _mm_storeu_si128((__m128i *)dst, p0);
81 0 : dst += dst_stride;
82 : _mm_storeu_si128((__m128i *)dst, p1);
83 0 : dst += dst_stride;
84 0 : h -= 2;
85 0 : } while (h > 0);
86 : } else { // width = 4
87 : __m128i p0, p1;
88 : do {
89 0 : p0 = _mm_loadl_epi64((const __m128i *)src);
90 0 : src += src_stride;
91 0 : p1 = _mm_loadl_epi64((const __m128i *)src);
92 0 : src += src_stride;
93 :
94 : _mm_storel_epi64((__m128i *)dst, p0);
95 0 : dst += dst_stride;
96 : _mm_storel_epi64((__m128i *)dst, p1);
97 0 : dst += dst_stride;
98 0 : h -= 2;
99 0 : } while (h > 0);
100 : }
101 0 : }
102 :
103 0 : void aom_highbd_convolve_avg_avx2(const uint8_t *src8, ptrdiff_t src_stride,
104 : uint8_t *dst8, ptrdiff_t dst_stride,
105 : const int16_t *filter_x, int filter_x_stride,
106 : const int16_t *filter_y, int filter_y_stride,
107 : int width, int h, int bd) {
108 0 : uint16_t *src = CONVERT_TO_SHORTPTR(src8);
109 0 : uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
110 : (void)filter_x;
111 : (void)filter_y;
112 : (void)filter_x_stride;
113 : (void)filter_y_stride;
114 : (void)bd;
115 :
116 0 : assert(width % 4 == 0);
117 0 : if (width > 32) { // width = 64
118 : __m256i p0, p1, p2, p3, u0, u1, u2, u3;
119 : do {
120 0 : p0 = _mm256_loadu_si256((const __m256i *)src);
121 0 : p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
122 0 : p2 = _mm256_loadu_si256((const __m256i *)(src + 32));
123 0 : p3 = _mm256_loadu_si256((const __m256i *)(src + 48));
124 0 : src += src_stride;
125 0 : u0 = _mm256_loadu_si256((const __m256i *)dst);
126 0 : u1 = _mm256_loadu_si256((const __m256i *)(dst + 16));
127 0 : u2 = _mm256_loadu_si256((const __m256i *)(dst + 32));
128 0 : u3 = _mm256_loadu_si256((const __m256i *)(dst + 48));
129 0 : _mm256_storeu_si256((__m256i *)dst, _mm256_avg_epu16(p0, u0));
130 0 : _mm256_storeu_si256((__m256i *)(dst + 16), _mm256_avg_epu16(p1, u1));
131 0 : _mm256_storeu_si256((__m256i *)(dst + 32), _mm256_avg_epu16(p2, u2));
132 0 : _mm256_storeu_si256((__m256i *)(dst + 48), _mm256_avg_epu16(p3, u3));
133 0 : dst += dst_stride;
134 0 : h--;
135 0 : } while (h > 0);
136 0 : } else if (width > 16) { // width = 32
137 : __m256i p0, p1, u0, u1;
138 : do {
139 0 : p0 = _mm256_loadu_si256((const __m256i *)src);
140 0 : p1 = _mm256_loadu_si256((const __m256i *)(src + 16));
141 0 : src += src_stride;
142 0 : u0 = _mm256_loadu_si256((const __m256i *)dst);
143 0 : u1 = _mm256_loadu_si256((const __m256i *)(dst + 16));
144 0 : _mm256_storeu_si256((__m256i *)dst, _mm256_avg_epu16(p0, u0));
145 0 : _mm256_storeu_si256((__m256i *)(dst + 16), _mm256_avg_epu16(p1, u1));
146 0 : dst += dst_stride;
147 0 : h--;
148 0 : } while (h > 0);
149 0 : } else if (width > 8) { // width = 16
150 : __m256i p0, p1, u0, u1;
151 : do {
152 0 : p0 = _mm256_loadu_si256((const __m256i *)src);
153 0 : p1 = _mm256_loadu_si256((const __m256i *)(src + src_stride));
154 0 : src += src_stride << 1;
155 0 : u0 = _mm256_loadu_si256((const __m256i *)dst);
156 0 : u1 = _mm256_loadu_si256((const __m256i *)(dst + dst_stride));
157 :
158 0 : _mm256_storeu_si256((__m256i *)dst, _mm256_avg_epu16(p0, u0));
159 0 : _mm256_storeu_si256((__m256i *)(dst + dst_stride),
160 : _mm256_avg_epu16(p1, u1));
161 0 : dst += dst_stride << 1;
162 0 : h -= 2;
163 0 : } while (h > 0);
164 0 : } else if (width > 4) { // width = 8
165 : __m128i p0, p1, u0, u1;
166 : do {
167 0 : p0 = _mm_loadu_si128((const __m128i *)src);
168 0 : p1 = _mm_loadu_si128((const __m128i *)(src + src_stride));
169 0 : src += src_stride << 1;
170 0 : u0 = _mm_loadu_si128((const __m128i *)dst);
171 0 : u1 = _mm_loadu_si128((const __m128i *)(dst + dst_stride));
172 :
173 0 : _mm_storeu_si128((__m128i *)dst, _mm_avg_epu16(p0, u0));
174 0 : _mm_storeu_si128((__m128i *)(dst + dst_stride), _mm_avg_epu16(p1, u1));
175 0 : dst += dst_stride << 1;
176 0 : h -= 2;
177 0 : } while (h > 0);
178 : } else { // width = 4
179 : __m128i p0, p1, u0, u1;
180 : do {
181 0 : p0 = _mm_loadl_epi64((const __m128i *)src);
182 0 : p1 = _mm_loadl_epi64((const __m128i *)(src + src_stride));
183 0 : src += src_stride << 1;
184 0 : u0 = _mm_loadl_epi64((const __m128i *)dst);
185 0 : u1 = _mm_loadl_epi64((const __m128i *)(dst + dst_stride));
186 :
187 0 : _mm_storel_epi64((__m128i *)dst, _mm_avg_epu16(u0, p0));
188 0 : _mm_storel_epi64((__m128i *)(dst + dst_stride), _mm_avg_epu16(u1, p1));
189 0 : dst += dst_stride << 1;
190 0 : h -= 2;
191 0 : } while (h > 0);
192 : }
193 0 : }
194 :
195 : // -----------------------------------------------------------------------------
196 : // Horizontal and vertical filtering
197 :
198 : #define CONV8_ROUNDING_BITS (7)
199 :
200 : static const uint8_t signal_pattern_0[32] = { 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6,
201 : 7, 6, 7, 8, 9, 0, 1, 2, 3, 2, 3,
202 : 4, 5, 4, 5, 6, 7, 6, 7, 8, 9 };
203 :
204 : static const uint8_t signal_pattern_1[32] = { 4, 5, 6, 7, 6, 7, 8, 9,
205 : 8, 9, 10, 11, 10, 11, 12, 13,
206 : 4, 5, 6, 7, 6, 7, 8, 9,
207 : 8, 9, 10, 11, 10, 11, 12, 13 };
208 :
209 : static const uint8_t signal_pattern_2[32] = { 6, 7, 8, 9, 8, 9, 10, 11,
210 : 10, 11, 12, 13, 12, 13, 14, 15,
211 : 6, 7, 8, 9, 8, 9, 10, 11,
212 : 10, 11, 12, 13, 12, 13, 14, 15 };
213 :
214 : static const uint32_t signal_index[8] = { 2, 3, 4, 5, 2, 3, 4, 5 };
215 :
216 : // -----------------------------------------------------------------------------
217 : // Horizontal Filtering
218 :
219 0 : static INLINE void pack_pixels(const __m256i *s, __m256i *p /*p[4]*/) {
220 0 : const __m256i idx = _mm256_loadu_si256((const __m256i *)signal_index);
221 0 : const __m256i sf0 = _mm256_loadu_si256((const __m256i *)signal_pattern_0);
222 0 : const __m256i sf1 = _mm256_loadu_si256((const __m256i *)signal_pattern_1);
223 0 : const __m256i c = _mm256_permutevar8x32_epi32(*s, idx);
224 :
225 0 : p[0] = _mm256_shuffle_epi8(*s, sf0); // x0x6
226 0 : p[1] = _mm256_shuffle_epi8(*s, sf1); // x1x7
227 0 : p[2] = _mm256_shuffle_epi8(c, sf0); // x2x4
228 0 : p[3] = _mm256_shuffle_epi8(c, sf1); // x3x5
229 0 : }
230 :
231 : // Note:
232 : // Shared by 8x2 and 16x1 block
233 0 : static INLINE void pack_16_pixels(const __m256i *s0, const __m256i *s1,
234 : __m256i *x /*x[8]*/) {
235 : __m256i pp[8];
236 0 : pack_pixels(s0, pp);
237 0 : pack_pixels(s1, &pp[4]);
238 0 : x[0] = _mm256_permute2x128_si256(pp[0], pp[4], 0x20);
239 0 : x[1] = _mm256_permute2x128_si256(pp[1], pp[5], 0x20);
240 0 : x[2] = _mm256_permute2x128_si256(pp[2], pp[6], 0x20);
241 0 : x[3] = _mm256_permute2x128_si256(pp[3], pp[7], 0x20);
242 0 : x[4] = x[2];
243 0 : x[5] = x[3];
244 0 : x[6] = _mm256_permute2x128_si256(pp[0], pp[4], 0x31);
245 0 : x[7] = _mm256_permute2x128_si256(pp[1], pp[5], 0x31);
246 0 : }
247 :
248 0 : static INLINE void pack_8x1_pixels(const uint16_t *src, __m256i *x) {
249 : __m256i pp[8];
250 : __m256i s0;
251 0 : s0 = _mm256_loadu_si256((const __m256i *)src);
252 0 : pack_pixels(&s0, pp);
253 0 : x[0] = _mm256_permute2x128_si256(pp[0], pp[2], 0x30);
254 0 : x[1] = _mm256_permute2x128_si256(pp[1], pp[3], 0x30);
255 0 : x[2] = _mm256_permute2x128_si256(pp[2], pp[0], 0x30);
256 0 : x[3] = _mm256_permute2x128_si256(pp[3], pp[1], 0x30);
257 0 : }
258 :
259 0 : static INLINE void pack_8x2_pixels(const uint16_t *src, ptrdiff_t stride,
260 : __m256i *x) {
261 : __m256i s0, s1;
262 0 : s0 = _mm256_loadu_si256((const __m256i *)src);
263 0 : s1 = _mm256_loadu_si256((const __m256i *)(src + stride));
264 0 : pack_16_pixels(&s0, &s1, x);
265 0 : }
266 :
267 0 : static INLINE void pack_16x1_pixels(const uint16_t *src, __m256i *x) {
268 : __m256i s0, s1;
269 0 : s0 = _mm256_loadu_si256((const __m256i *)src);
270 0 : s1 = _mm256_loadu_si256((const __m256i *)(src + 8));
271 0 : pack_16_pixels(&s0, &s1, x);
272 0 : }
273 :
274 : // Note:
275 : // Shared by horizontal and vertical filtering
276 0 : static INLINE void pack_filters(const int16_t *filter, __m256i *f /*f[4]*/) {
277 0 : const __m128i h = _mm_loadu_si128((const __m128i *)filter);
278 0 : const __m256i hh = _mm256_insertf128_si256(_mm256_castsi128_si256(h), h, 1);
279 0 : const __m256i p0 = _mm256_set1_epi32(0x03020100);
280 0 : const __m256i p1 = _mm256_set1_epi32(0x07060504);
281 0 : const __m256i p2 = _mm256_set1_epi32(0x0b0a0908);
282 0 : const __m256i p3 = _mm256_set1_epi32(0x0f0e0d0c);
283 0 : f[0] = _mm256_shuffle_epi8(hh, p0);
284 0 : f[1] = _mm256_shuffle_epi8(hh, p1);
285 0 : f[2] = _mm256_shuffle_epi8(hh, p2);
286 0 : f[3] = _mm256_shuffle_epi8(hh, p3);
287 0 : }
288 :
289 0 : static INLINE void filter_8x1_pixels(const __m256i *sig /*sig[4]*/,
290 : const __m256i *fil /*fil[4]*/,
291 : __m256i *y) {
292 : __m256i a, a0, a1;
293 :
294 0 : a0 = _mm256_madd_epi16(fil[0], sig[0]);
295 0 : a1 = _mm256_madd_epi16(fil[3], sig[3]);
296 0 : a = _mm256_add_epi32(a0, a1);
297 :
298 0 : a0 = _mm256_madd_epi16(fil[1], sig[1]);
299 0 : a1 = _mm256_madd_epi16(fil[2], sig[2]);
300 :
301 : {
302 0 : const __m256i min = _mm256_min_epi32(a0, a1);
303 0 : a = _mm256_add_epi32(a, min);
304 : }
305 : {
306 0 : const __m256i max = _mm256_max_epi32(a0, a1);
307 0 : a = _mm256_add_epi32(a, max);
308 : }
309 : {
310 0 : const __m256i rounding = _mm256_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
311 0 : a = _mm256_add_epi32(a, rounding);
312 0 : *y = _mm256_srai_epi32(a, CONV8_ROUNDING_BITS);
313 : }
314 0 : }
315 :
316 0 : static INLINE void store_8x1_pixels(const __m256i *y, const __m256i *mask,
317 : uint16_t *dst) {
318 0 : const __m128i a0 = _mm256_castsi256_si128(*y);
319 0 : const __m128i a1 = _mm256_extractf128_si256(*y, 1);
320 0 : __m128i res = _mm_packus_epi32(a0, a1);
321 0 : res = _mm_min_epi16(res, _mm256_castsi256_si128(*mask));
322 : _mm_storeu_si128((__m128i *)dst, res);
323 0 : }
324 :
325 0 : static INLINE void store_8x2_pixels(const __m256i *y0, const __m256i *y1,
326 : const __m256i *mask, uint16_t *dst,
327 : ptrdiff_t pitch) {
328 0 : __m256i a = _mm256_packus_epi32(*y0, *y1);
329 0 : a = _mm256_min_epi16(a, *mask);
330 0 : _mm_storeu_si128((__m128i *)dst, _mm256_castsi256_si128(a));
331 0 : _mm_storeu_si128((__m128i *)(dst + pitch), _mm256_extractf128_si256(a, 1));
332 0 : }
333 :
334 0 : static INLINE void store_16x1_pixels(const __m256i *y0, const __m256i *y1,
335 : const __m256i *mask, uint16_t *dst) {
336 0 : __m256i a = _mm256_packus_epi32(*y0, *y1);
337 0 : a = _mm256_min_epi16(a, *mask);
338 : _mm256_storeu_si256((__m256i *)dst, a);
339 0 : }
340 :
341 0 : static void aom_highbd_filter_block1d8_h8_avx2(
342 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
343 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
344 : __m256i signal[8], res0, res1;
345 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
346 :
347 : __m256i ff[4];
348 0 : pack_filters(filter, ff);
349 :
350 0 : src_ptr -= 3;
351 : do {
352 0 : pack_8x2_pixels(src_ptr, src_pitch, signal);
353 0 : filter_8x1_pixels(signal, ff, &res0);
354 0 : filter_8x1_pixels(&signal[4], ff, &res1);
355 0 : store_8x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
356 0 : height -= 2;
357 0 : src_ptr += src_pitch << 1;
358 0 : dst_ptr += dst_pitch << 1;
359 0 : } while (height > 1);
360 :
361 0 : if (height > 0) {
362 0 : pack_8x1_pixels(src_ptr, signal);
363 0 : filter_8x1_pixels(signal, ff, &res0);
364 0 : store_8x1_pixels(&res0, &max, dst_ptr);
365 : }
366 0 : }
367 :
368 0 : static void aom_highbd_filter_block1d16_h8_avx2(
369 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
370 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
371 : __m256i signal[8], res0, res1;
372 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
373 :
374 : __m256i ff[4];
375 0 : pack_filters(filter, ff);
376 :
377 0 : src_ptr -= 3;
378 : do {
379 0 : pack_16x1_pixels(src_ptr, signal);
380 0 : filter_8x1_pixels(signal, ff, &res0);
381 0 : filter_8x1_pixels(&signal[4], ff, &res1);
382 0 : store_16x1_pixels(&res0, &res1, &max, dst_ptr);
383 0 : height -= 1;
384 0 : src_ptr += src_pitch;
385 0 : dst_ptr += dst_pitch;
386 0 : } while (height > 0);
387 0 : }
388 :
389 : // -----------------------------------------------------------------------------
390 : // 2-tap horizontal filtering
391 :
392 0 : static INLINE void pack_2t_filter(const int16_t *filter, __m256i *f) {
393 0 : const __m128i h = _mm_loadu_si128((const __m128i *)filter);
394 0 : const __m256i hh = _mm256_insertf128_si256(_mm256_castsi128_si256(h), h, 1);
395 0 : const __m256i p = _mm256_set1_epi32(0x09080706);
396 0 : f[0] = _mm256_shuffle_epi8(hh, p);
397 0 : }
398 :
399 : // can be used by pack_8x2_2t_pixels() and pack_16x1_2t_pixels()
400 : // the difference is s0/s1 specifies first and second rows or,
401 : // first 16 samples and 8-sample shifted 16 samples
402 0 : static INLINE void pack_16_2t_pixels(const __m256i *s0, const __m256i *s1,
403 : __m256i *sig) {
404 0 : const __m256i idx = _mm256_loadu_si256((const __m256i *)signal_index);
405 0 : const __m256i sf2 = _mm256_loadu_si256((const __m256i *)signal_pattern_2);
406 0 : __m256i x0 = _mm256_shuffle_epi8(*s0, sf2);
407 0 : __m256i x1 = _mm256_shuffle_epi8(*s1, sf2);
408 0 : __m256i r0 = _mm256_permutevar8x32_epi32(*s0, idx);
409 0 : __m256i r1 = _mm256_permutevar8x32_epi32(*s1, idx);
410 0 : r0 = _mm256_shuffle_epi8(r0, sf2);
411 0 : r1 = _mm256_shuffle_epi8(r1, sf2);
412 0 : sig[0] = _mm256_permute2x128_si256(x0, x1, 0x20);
413 0 : sig[1] = _mm256_permute2x128_si256(r0, r1, 0x20);
414 0 : }
415 :
416 0 : static INLINE void pack_8x2_2t_pixels(const uint16_t *src,
417 : const ptrdiff_t pitch, __m256i *sig) {
418 0 : const __m256i r0 = _mm256_loadu_si256((const __m256i *)src);
419 0 : const __m256i r1 = _mm256_loadu_si256((const __m256i *)(src + pitch));
420 0 : pack_16_2t_pixels(&r0, &r1, sig);
421 0 : }
422 :
423 0 : static INLINE void pack_16x1_2t_pixels(const uint16_t *src,
424 : __m256i *sig /*sig[2]*/) {
425 0 : const __m256i r0 = _mm256_loadu_si256((const __m256i *)src);
426 0 : const __m256i r1 = _mm256_loadu_si256((const __m256i *)(src + 8));
427 0 : pack_16_2t_pixels(&r0, &r1, sig);
428 0 : }
429 :
430 0 : static INLINE void pack_8x1_2t_pixels(const uint16_t *src,
431 : __m256i *sig /*sig[2]*/) {
432 0 : const __m256i idx = _mm256_loadu_si256((const __m256i *)signal_index);
433 0 : const __m256i sf2 = _mm256_loadu_si256((const __m256i *)signal_pattern_2);
434 0 : __m256i r0 = _mm256_loadu_si256((const __m256i *)src);
435 0 : __m256i x0 = _mm256_shuffle_epi8(r0, sf2);
436 0 : r0 = _mm256_permutevar8x32_epi32(r0, idx);
437 0 : r0 = _mm256_shuffle_epi8(r0, sf2);
438 0 : sig[0] = _mm256_permute2x128_si256(x0, r0, 0x20);
439 0 : }
440 :
441 : // can be used by filter_8x2_2t_pixels() and filter_16x1_2t_pixels()
442 0 : static INLINE void filter_16_2t_pixels(const __m256i *sig, const __m256i *f,
443 : __m256i *y0, __m256i *y1) {
444 0 : const __m256i rounding = _mm256_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
445 0 : __m256i x0 = _mm256_madd_epi16(sig[0], *f);
446 0 : __m256i x1 = _mm256_madd_epi16(sig[1], *f);
447 0 : x0 = _mm256_add_epi32(x0, rounding);
448 0 : x1 = _mm256_add_epi32(x1, rounding);
449 0 : *y0 = _mm256_srai_epi32(x0, CONV8_ROUNDING_BITS);
450 0 : *y1 = _mm256_srai_epi32(x1, CONV8_ROUNDING_BITS);
451 0 : }
452 :
453 0 : static INLINE void filter_8x1_2t_pixels(const __m256i *sig, const __m256i *f,
454 : __m256i *y0) {
455 0 : const __m256i rounding = _mm256_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
456 0 : __m256i x0 = _mm256_madd_epi16(sig[0], *f);
457 0 : x0 = _mm256_add_epi32(x0, rounding);
458 0 : *y0 = _mm256_srai_epi32(x0, CONV8_ROUNDING_BITS);
459 0 : }
460 :
461 0 : static void aom_highbd_filter_block1d8_h2_avx2(
462 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
463 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
464 : __m256i signal[2], res0, res1;
465 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
466 :
467 : __m256i ff;
468 0 : pack_2t_filter(filter, &ff);
469 :
470 0 : src_ptr -= 3;
471 : do {
472 0 : pack_8x2_2t_pixels(src_ptr, src_pitch, signal);
473 0 : filter_16_2t_pixels(signal, &ff, &res0, &res1);
474 0 : store_8x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
475 0 : height -= 2;
476 0 : src_ptr += src_pitch << 1;
477 0 : dst_ptr += dst_pitch << 1;
478 0 : } while (height > 1);
479 :
480 0 : if (height > 0) {
481 0 : pack_8x1_2t_pixels(src_ptr, signal);
482 0 : filter_8x1_2t_pixels(signal, &ff, &res0);
483 0 : store_8x1_pixels(&res0, &max, dst_ptr);
484 : }
485 0 : }
486 :
487 0 : static void aom_highbd_filter_block1d16_h2_avx2(
488 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
489 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
490 : __m256i signal[2], res0, res1;
491 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
492 :
493 : __m256i ff;
494 0 : pack_2t_filter(filter, &ff);
495 :
496 0 : src_ptr -= 3;
497 : do {
498 0 : pack_16x1_2t_pixels(src_ptr, signal);
499 0 : filter_16_2t_pixels(signal, &ff, &res0, &res1);
500 0 : store_16x1_pixels(&res0, &res1, &max, dst_ptr);
501 0 : height -= 1;
502 0 : src_ptr += src_pitch;
503 0 : dst_ptr += dst_pitch;
504 0 : } while (height > 0);
505 0 : }
506 :
507 : // -----------------------------------------------------------------------------
508 : // Vertical Filtering
509 :
510 0 : static void pack_8x9_init(const uint16_t *src, ptrdiff_t pitch, __m256i *sig) {
511 0 : __m256i s0 = _mm256_castsi128_si256(_mm_loadu_si128((const __m128i *)src));
512 0 : __m256i s1 =
513 0 : _mm256_castsi128_si256(_mm_loadu_si128((const __m128i *)(src + pitch)));
514 0 : __m256i s2 = _mm256_castsi128_si256(
515 0 : _mm_loadu_si128((const __m128i *)(src + 2 * pitch)));
516 0 : __m256i s3 = _mm256_castsi128_si256(
517 0 : _mm_loadu_si128((const __m128i *)(src + 3 * pitch)));
518 0 : __m256i s4 = _mm256_castsi128_si256(
519 0 : _mm_loadu_si128((const __m128i *)(src + 4 * pitch)));
520 0 : __m256i s5 = _mm256_castsi128_si256(
521 0 : _mm_loadu_si128((const __m128i *)(src + 5 * pitch)));
522 0 : __m256i s6 = _mm256_castsi128_si256(
523 0 : _mm_loadu_si128((const __m128i *)(src + 6 * pitch)));
524 :
525 0 : s0 = _mm256_inserti128_si256(s0, _mm256_castsi256_si128(s1), 1);
526 0 : s1 = _mm256_inserti128_si256(s1, _mm256_castsi256_si128(s2), 1);
527 0 : s2 = _mm256_inserti128_si256(s2, _mm256_castsi256_si128(s3), 1);
528 0 : s3 = _mm256_inserti128_si256(s3, _mm256_castsi256_si128(s4), 1);
529 0 : s4 = _mm256_inserti128_si256(s4, _mm256_castsi256_si128(s5), 1);
530 0 : s5 = _mm256_inserti128_si256(s5, _mm256_castsi256_si128(s6), 1);
531 :
532 0 : sig[0] = _mm256_unpacklo_epi16(s0, s1);
533 0 : sig[4] = _mm256_unpackhi_epi16(s0, s1);
534 0 : sig[1] = _mm256_unpacklo_epi16(s2, s3);
535 0 : sig[5] = _mm256_unpackhi_epi16(s2, s3);
536 0 : sig[2] = _mm256_unpacklo_epi16(s4, s5);
537 0 : sig[6] = _mm256_unpackhi_epi16(s4, s5);
538 0 : sig[8] = s6;
539 0 : }
540 :
541 0 : static INLINE void pack_8x9_pixels(const uint16_t *src, ptrdiff_t pitch,
542 : __m256i *sig) {
543 : // base + 7th row
544 0 : __m256i s0 = _mm256_castsi128_si256(
545 0 : _mm_loadu_si128((const __m128i *)(src + 7 * pitch)));
546 : // base + 8th row
547 0 : __m256i s1 = _mm256_castsi128_si256(
548 0 : _mm_loadu_si128((const __m128i *)(src + 8 * pitch)));
549 0 : __m256i s2 = _mm256_inserti128_si256(sig[8], _mm256_castsi256_si128(s0), 1);
550 0 : __m256i s3 = _mm256_inserti128_si256(s0, _mm256_castsi256_si128(s1), 1);
551 0 : sig[3] = _mm256_unpacklo_epi16(s2, s3);
552 0 : sig[7] = _mm256_unpackhi_epi16(s2, s3);
553 0 : sig[8] = s1;
554 0 : }
555 :
556 0 : static INLINE void filter_8x9_pixels(const __m256i *sig, const __m256i *f,
557 : __m256i *y0, __m256i *y1) {
558 0 : filter_8x1_pixels(sig, f, y0);
559 0 : filter_8x1_pixels(&sig[4], f, y1);
560 0 : }
561 :
562 0 : static INLINE void update_pixels(__m256i *sig) {
563 : int i;
564 0 : for (i = 0; i < 3; ++i) {
565 0 : sig[i] = sig[i + 1];
566 0 : sig[i + 4] = sig[i + 5];
567 : }
568 0 : }
569 :
570 0 : static void aom_highbd_filter_block1d8_v8_avx2(
571 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
572 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
573 : __m256i signal[9], res0, res1;
574 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
575 :
576 : __m256i ff[4];
577 0 : pack_filters(filter, ff);
578 :
579 0 : pack_8x9_init(src_ptr, src_pitch, signal);
580 :
581 : do {
582 0 : pack_8x9_pixels(src_ptr, src_pitch, signal);
583 :
584 0 : filter_8x9_pixels(signal, ff, &res0, &res1);
585 0 : store_8x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
586 0 : update_pixels(signal);
587 :
588 0 : src_ptr += src_pitch << 1;
589 0 : dst_ptr += dst_pitch << 1;
590 0 : height -= 2;
591 0 : } while (height > 0);
592 0 : }
593 :
594 0 : static void pack_16x9_init(const uint16_t *src, ptrdiff_t pitch, __m256i *sig) {
595 : __m256i u0, u1, u2, u3;
596 : // load 0-6 rows
597 0 : const __m256i s0 = _mm256_loadu_si256((const __m256i *)src);
598 0 : const __m256i s1 = _mm256_loadu_si256((const __m256i *)(src + pitch));
599 0 : const __m256i s2 = _mm256_loadu_si256((const __m256i *)(src + 2 * pitch));
600 0 : const __m256i s3 = _mm256_loadu_si256((const __m256i *)(src + 3 * pitch));
601 0 : const __m256i s4 = _mm256_loadu_si256((const __m256i *)(src + 4 * pitch));
602 0 : const __m256i s5 = _mm256_loadu_si256((const __m256i *)(src + 5 * pitch));
603 0 : const __m256i s6 = _mm256_loadu_si256((const __m256i *)(src + 6 * pitch));
604 :
605 0 : u0 = _mm256_permute2x128_si256(s0, s1, 0x20); // 0, 1 low
606 0 : u1 = _mm256_permute2x128_si256(s0, s1, 0x31); // 0, 1 high
607 :
608 0 : u2 = _mm256_permute2x128_si256(s1, s2, 0x20); // 1, 2 low
609 0 : u3 = _mm256_permute2x128_si256(s1, s2, 0x31); // 1, 2 high
610 :
611 0 : sig[0] = _mm256_unpacklo_epi16(u0, u2);
612 0 : sig[4] = _mm256_unpackhi_epi16(u0, u2);
613 :
614 0 : sig[8] = _mm256_unpacklo_epi16(u1, u3);
615 0 : sig[12] = _mm256_unpackhi_epi16(u1, u3);
616 :
617 0 : u0 = _mm256_permute2x128_si256(s2, s3, 0x20);
618 0 : u1 = _mm256_permute2x128_si256(s2, s3, 0x31);
619 :
620 0 : u2 = _mm256_permute2x128_si256(s3, s4, 0x20);
621 0 : u3 = _mm256_permute2x128_si256(s3, s4, 0x31);
622 :
623 0 : sig[1] = _mm256_unpacklo_epi16(u0, u2);
624 0 : sig[5] = _mm256_unpackhi_epi16(u0, u2);
625 :
626 0 : sig[9] = _mm256_unpacklo_epi16(u1, u3);
627 0 : sig[13] = _mm256_unpackhi_epi16(u1, u3);
628 :
629 0 : u0 = _mm256_permute2x128_si256(s4, s5, 0x20);
630 0 : u1 = _mm256_permute2x128_si256(s4, s5, 0x31);
631 :
632 0 : u2 = _mm256_permute2x128_si256(s5, s6, 0x20);
633 0 : u3 = _mm256_permute2x128_si256(s5, s6, 0x31);
634 :
635 0 : sig[2] = _mm256_unpacklo_epi16(u0, u2);
636 0 : sig[6] = _mm256_unpackhi_epi16(u0, u2);
637 :
638 0 : sig[10] = _mm256_unpacklo_epi16(u1, u3);
639 0 : sig[14] = _mm256_unpackhi_epi16(u1, u3);
640 :
641 0 : sig[16] = s6;
642 0 : }
643 :
644 0 : static void pack_16x9_pixels(const uint16_t *src, ptrdiff_t pitch,
645 : __m256i *sig) {
646 : // base + 7th row
647 0 : const __m256i s7 = _mm256_loadu_si256((const __m256i *)(src + 7 * pitch));
648 : // base + 8th row
649 0 : const __m256i s8 = _mm256_loadu_si256((const __m256i *)(src + 8 * pitch));
650 :
651 : __m256i u0, u1, u2, u3;
652 0 : u0 = _mm256_permute2x128_si256(sig[16], s7, 0x20);
653 0 : u1 = _mm256_permute2x128_si256(sig[16], s7, 0x31);
654 :
655 0 : u2 = _mm256_permute2x128_si256(s7, s8, 0x20);
656 0 : u3 = _mm256_permute2x128_si256(s7, s8, 0x31);
657 :
658 0 : sig[3] = _mm256_unpacklo_epi16(u0, u2);
659 0 : sig[7] = _mm256_unpackhi_epi16(u0, u2);
660 :
661 0 : sig[11] = _mm256_unpacklo_epi16(u1, u3);
662 0 : sig[15] = _mm256_unpackhi_epi16(u1, u3);
663 :
664 0 : sig[16] = s8;
665 0 : }
666 :
667 0 : static INLINE void filter_16x9_pixels(const __m256i *sig, const __m256i *f,
668 : __m256i *y0, __m256i *y1) {
669 : __m256i res[4];
670 : int i;
671 0 : for (i = 0; i < 4; ++i) {
672 0 : filter_8x1_pixels(&sig[i << 2], f, &res[i]);
673 : }
674 :
675 : {
676 0 : const __m256i l0l1 = _mm256_packus_epi32(res[0], res[1]);
677 0 : const __m256i h0h1 = _mm256_packus_epi32(res[2], res[3]);
678 0 : *y0 = _mm256_permute2x128_si256(l0l1, h0h1, 0x20);
679 0 : *y1 = _mm256_permute2x128_si256(l0l1, h0h1, 0x31);
680 : }
681 0 : }
682 :
683 0 : static INLINE void store_16x2_pixels(const __m256i *y0, const __m256i *y1,
684 : const __m256i *mask, uint16_t *dst,
685 : ptrdiff_t pitch) {
686 0 : __m256i p = _mm256_min_epi16(*y0, *mask);
687 : _mm256_storeu_si256((__m256i *)dst, p);
688 0 : p = _mm256_min_epi16(*y1, *mask);
689 0 : _mm256_storeu_si256((__m256i *)(dst + pitch), p);
690 0 : }
691 :
692 0 : static void update_16x9_pixels(__m256i *sig) {
693 0 : update_pixels(&sig[0]);
694 0 : update_pixels(&sig[8]);
695 0 : }
696 :
697 0 : static void aom_highbd_filter_block1d16_v8_avx2(
698 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
699 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
700 : __m256i signal[17], res0, res1;
701 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
702 :
703 : __m256i ff[4];
704 0 : pack_filters(filter, ff);
705 :
706 0 : pack_16x9_init(src_ptr, src_pitch, signal);
707 :
708 : do {
709 0 : pack_16x9_pixels(src_ptr, src_pitch, signal);
710 0 : filter_16x9_pixels(signal, ff, &res0, &res1);
711 0 : store_16x2_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
712 0 : update_16x9_pixels(signal);
713 :
714 0 : src_ptr += src_pitch << 1;
715 0 : dst_ptr += dst_pitch << 1;
716 0 : height -= 2;
717 0 : } while (height > 0);
718 0 : }
719 :
720 : // -----------------------------------------------------------------------------
721 : // 2-tap vertical filtering
722 :
723 0 : static void pack_16x2_init(const uint16_t *src, __m256i *sig) {
724 0 : sig[2] = _mm256_loadu_si256((const __m256i *)src);
725 0 : }
726 :
727 0 : static INLINE void pack_16x2_2t_pixels(const uint16_t *src, ptrdiff_t pitch,
728 : __m256i *sig) {
729 : // load the next row
730 0 : const __m256i u = _mm256_loadu_si256((const __m256i *)(src + pitch));
731 0 : sig[0] = _mm256_unpacklo_epi16(sig[2], u);
732 0 : sig[1] = _mm256_unpackhi_epi16(sig[2], u);
733 0 : sig[2] = u;
734 0 : }
735 :
736 0 : static INLINE void filter_16x2_2t_pixels(const __m256i *sig, const __m256i *f,
737 : __m256i *y0, __m256i *y1) {
738 0 : filter_16_2t_pixels(sig, f, y0, y1);
739 0 : }
740 :
741 0 : static void aom_highbd_filter_block1d16_v2_avx2(
742 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
743 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
744 : __m256i signal[3], res0, res1;
745 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
746 : __m256i ff;
747 :
748 0 : pack_2t_filter(filter, &ff);
749 0 : pack_16x2_init(src_ptr, signal);
750 :
751 : do {
752 0 : pack_16x2_2t_pixels(src_ptr, src_pitch, signal);
753 0 : filter_16x2_2t_pixels(signal, &ff, &res0, &res1);
754 0 : store_16x1_pixels(&res0, &res1, &max, dst_ptr);
755 :
756 0 : src_ptr += src_pitch;
757 0 : dst_ptr += dst_pitch;
758 0 : height -= 1;
759 0 : } while (height > 0);
760 0 : }
761 :
762 0 : static INLINE void pack_8x1_2t_filter(const int16_t *filter, __m128i *f) {
763 0 : const __m128i h = _mm_loadu_si128((const __m128i *)filter);
764 0 : const __m128i p = _mm_set1_epi32(0x09080706);
765 0 : f[0] = _mm_shuffle_epi8(h, p);
766 0 : }
767 :
768 0 : static void pack_8x2_init(const uint16_t *src, __m128i *sig) {
769 0 : sig[2] = _mm_loadu_si128((const __m128i *)src);
770 0 : }
771 :
772 0 : static INLINE void pack_8x2_2t_pixels_ver(const uint16_t *src, ptrdiff_t pitch,
773 : __m128i *sig) {
774 : // load the next row
775 0 : const __m128i u = _mm_loadu_si128((const __m128i *)(src + pitch));
776 0 : sig[0] = _mm_unpacklo_epi16(sig[2], u);
777 0 : sig[1] = _mm_unpackhi_epi16(sig[2], u);
778 0 : sig[2] = u;
779 0 : }
780 :
781 0 : static INLINE void filter_8_2t_pixels(const __m128i *sig, const __m128i *f,
782 : __m128i *y0, __m128i *y1) {
783 0 : const __m128i rounding = _mm_set1_epi32(1 << (CONV8_ROUNDING_BITS - 1));
784 0 : __m128i x0 = _mm_madd_epi16(sig[0], *f);
785 0 : __m128i x1 = _mm_madd_epi16(sig[1], *f);
786 0 : x0 = _mm_add_epi32(x0, rounding);
787 0 : x1 = _mm_add_epi32(x1, rounding);
788 0 : *y0 = _mm_srai_epi32(x0, CONV8_ROUNDING_BITS);
789 0 : *y1 = _mm_srai_epi32(x1, CONV8_ROUNDING_BITS);
790 0 : }
791 :
792 0 : static INLINE void store_8x1_2t_pixels_ver(const __m128i *y0, const __m128i *y1,
793 : const __m128i *mask, uint16_t *dst) {
794 0 : __m128i res = _mm_packus_epi32(*y0, *y1);
795 0 : res = _mm_min_epi16(res, *mask);
796 : _mm_storeu_si128((__m128i *)dst, res);
797 0 : }
798 :
799 0 : static void aom_highbd_filter_block1d8_v2_avx2(
800 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
801 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
802 : __m128i signal[3], res0, res1;
803 0 : const __m128i max = _mm_set1_epi16((1 << bd) - 1);
804 : __m128i ff;
805 :
806 0 : pack_8x1_2t_filter(filter, &ff);
807 0 : pack_8x2_init(src_ptr, signal);
808 :
809 : do {
810 0 : pack_8x2_2t_pixels_ver(src_ptr, src_pitch, signal);
811 0 : filter_8_2t_pixels(signal, &ff, &res0, &res1);
812 0 : store_8x1_2t_pixels_ver(&res0, &res1, &max, dst_ptr);
813 :
814 0 : src_ptr += src_pitch;
815 0 : dst_ptr += dst_pitch;
816 0 : height -= 1;
817 0 : } while (height > 0);
818 0 : }
819 :
820 : // Calculation with averaging the input pixels
821 :
822 0 : static INLINE void store_8x1_avg_pixels(const __m256i *y0, const __m256i *mask,
823 : uint16_t *dst) {
824 0 : const __m128i a0 = _mm256_castsi256_si128(*y0);
825 0 : const __m128i a1 = _mm256_extractf128_si256(*y0, 1);
826 0 : __m128i res = _mm_packus_epi32(a0, a1);
827 0 : const __m128i pix = _mm_loadu_si128((const __m128i *)dst);
828 0 : res = _mm_min_epi16(res, _mm256_castsi256_si128(*mask));
829 0 : res = _mm_avg_epu16(res, pix);
830 : _mm_storeu_si128((__m128i *)dst, res);
831 0 : }
832 :
833 0 : static INLINE void store_8x2_avg_pixels(const __m256i *y0, const __m256i *y1,
834 : const __m256i *mask, uint16_t *dst,
835 : ptrdiff_t pitch) {
836 0 : __m256i a = _mm256_packus_epi32(*y0, *y1);
837 0 : const __m128i pix0 = _mm_loadu_si128((const __m128i *)dst);
838 0 : const __m128i pix1 = _mm_loadu_si128((const __m128i *)(dst + pitch));
839 0 : const __m256i pix =
840 0 : _mm256_insertf128_si256(_mm256_castsi128_si256(pix0), pix1, 1);
841 0 : a = _mm256_min_epi16(a, *mask);
842 0 : a = _mm256_avg_epu16(a, pix);
843 0 : _mm_storeu_si128((__m128i *)dst, _mm256_castsi256_si128(a));
844 0 : _mm_storeu_si128((__m128i *)(dst + pitch), _mm256_extractf128_si256(a, 1));
845 0 : }
846 :
847 0 : static INLINE void store_16x1_avg_pixels(const __m256i *y0, const __m256i *y1,
848 : const __m256i *mask, uint16_t *dst) {
849 0 : __m256i a = _mm256_packus_epi32(*y0, *y1);
850 0 : const __m256i pix = _mm256_loadu_si256((const __m256i *)dst);
851 0 : a = _mm256_min_epi16(a, *mask);
852 0 : a = _mm256_avg_epu16(a, pix);
853 : _mm256_storeu_si256((__m256i *)dst, a);
854 0 : }
855 :
856 0 : static INLINE void store_16x2_avg_pixels(const __m256i *y0, const __m256i *y1,
857 : const __m256i *mask, uint16_t *dst,
858 : ptrdiff_t pitch) {
859 0 : const __m256i pix0 = _mm256_loadu_si256((const __m256i *)dst);
860 0 : const __m256i pix1 = _mm256_loadu_si256((const __m256i *)(dst + pitch));
861 0 : __m256i p = _mm256_min_epi16(*y0, *mask);
862 0 : p = _mm256_avg_epu16(p, pix0);
863 : _mm256_storeu_si256((__m256i *)dst, p);
864 :
865 0 : p = _mm256_min_epi16(*y1, *mask);
866 0 : p = _mm256_avg_epu16(p, pix1);
867 0 : _mm256_storeu_si256((__m256i *)(dst + pitch), p);
868 0 : }
869 :
870 0 : static INLINE void store_8x1_2t_avg_pixels_ver(const __m128i *y0,
871 : const __m128i *y1,
872 : const __m128i *mask,
873 : uint16_t *dst) {
874 0 : __m128i res = _mm_packus_epi32(*y0, *y1);
875 0 : const __m128i pix = _mm_loadu_si128((const __m128i *)dst);
876 0 : res = _mm_min_epi16(res, *mask);
877 0 : res = _mm_avg_epu16(res, pix);
878 : _mm_storeu_si128((__m128i *)dst, res);
879 0 : }
880 :
881 0 : static void aom_highbd_filter_block1d8_h8_avg_avx2(
882 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
883 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
884 : __m256i signal[8], res0, res1;
885 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
886 :
887 : __m256i ff[4];
888 0 : pack_filters(filter, ff);
889 :
890 0 : src_ptr -= 3;
891 : do {
892 0 : pack_8x2_pixels(src_ptr, src_pitch, signal);
893 0 : filter_8x1_pixels(signal, ff, &res0);
894 0 : filter_8x1_pixels(&signal[4], ff, &res1);
895 0 : store_8x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
896 0 : height -= 2;
897 0 : src_ptr += src_pitch << 1;
898 0 : dst_ptr += dst_pitch << 1;
899 0 : } while (height > 1);
900 :
901 0 : if (height > 0) {
902 0 : pack_8x1_pixels(src_ptr, signal);
903 0 : filter_8x1_pixels(signal, ff, &res0);
904 0 : store_8x1_avg_pixels(&res0, &max, dst_ptr);
905 : }
906 0 : }
907 :
908 0 : static void aom_highbd_filter_block1d16_h8_avg_avx2(
909 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
910 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
911 : __m256i signal[8], res0, res1;
912 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
913 :
914 : __m256i ff[4];
915 0 : pack_filters(filter, ff);
916 :
917 0 : src_ptr -= 3;
918 : do {
919 0 : pack_16x1_pixels(src_ptr, signal);
920 0 : filter_8x1_pixels(signal, ff, &res0);
921 0 : filter_8x1_pixels(&signal[4], ff, &res1);
922 0 : store_16x1_avg_pixels(&res0, &res1, &max, dst_ptr);
923 0 : height -= 1;
924 0 : src_ptr += src_pitch;
925 0 : dst_ptr += dst_pitch;
926 0 : } while (height > 0);
927 0 : }
928 :
929 0 : static void aom_highbd_filter_block1d8_v8_avg_avx2(
930 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
931 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
932 : __m256i signal[9], res0, res1;
933 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
934 :
935 : __m256i ff[4];
936 0 : pack_filters(filter, ff);
937 :
938 0 : pack_8x9_init(src_ptr, src_pitch, signal);
939 :
940 : do {
941 0 : pack_8x9_pixels(src_ptr, src_pitch, signal);
942 :
943 0 : filter_8x9_pixels(signal, ff, &res0, &res1);
944 0 : store_8x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
945 0 : update_pixels(signal);
946 :
947 0 : src_ptr += src_pitch << 1;
948 0 : dst_ptr += dst_pitch << 1;
949 0 : height -= 2;
950 0 : } while (height > 0);
951 0 : }
952 :
953 0 : static void aom_highbd_filter_block1d16_v8_avg_avx2(
954 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
955 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
956 : __m256i signal[17], res0, res1;
957 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
958 :
959 : __m256i ff[4];
960 0 : pack_filters(filter, ff);
961 :
962 0 : pack_16x9_init(src_ptr, src_pitch, signal);
963 :
964 : do {
965 0 : pack_16x9_pixels(src_ptr, src_pitch, signal);
966 0 : filter_16x9_pixels(signal, ff, &res0, &res1);
967 0 : store_16x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
968 0 : update_16x9_pixels(signal);
969 :
970 0 : src_ptr += src_pitch << 1;
971 0 : dst_ptr += dst_pitch << 1;
972 0 : height -= 2;
973 0 : } while (height > 0);
974 0 : }
975 :
976 0 : static void aom_highbd_filter_block1d8_h2_avg_avx2(
977 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
978 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
979 : __m256i signal[2], res0, res1;
980 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
981 :
982 : __m256i ff;
983 0 : pack_2t_filter(filter, &ff);
984 :
985 0 : src_ptr -= 3;
986 : do {
987 0 : pack_8x2_2t_pixels(src_ptr, src_pitch, signal);
988 0 : filter_16_2t_pixels(signal, &ff, &res0, &res1);
989 0 : store_8x2_avg_pixels(&res0, &res1, &max, dst_ptr, dst_pitch);
990 0 : height -= 2;
991 0 : src_ptr += src_pitch << 1;
992 0 : dst_ptr += dst_pitch << 1;
993 0 : } while (height > 1);
994 :
995 0 : if (height > 0) {
996 0 : pack_8x1_2t_pixels(src_ptr, signal);
997 0 : filter_8x1_2t_pixels(signal, &ff, &res0);
998 0 : store_8x1_avg_pixels(&res0, &max, dst_ptr);
999 : }
1000 0 : }
1001 :
1002 0 : static void aom_highbd_filter_block1d16_h2_avg_avx2(
1003 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
1004 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
1005 : __m256i signal[2], res0, res1;
1006 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
1007 :
1008 : __m256i ff;
1009 0 : pack_2t_filter(filter, &ff);
1010 :
1011 0 : src_ptr -= 3;
1012 : do {
1013 0 : pack_16x1_2t_pixels(src_ptr, signal);
1014 0 : filter_16_2t_pixels(signal, &ff, &res0, &res1);
1015 0 : store_16x1_avg_pixels(&res0, &res1, &max, dst_ptr);
1016 0 : height -= 1;
1017 0 : src_ptr += src_pitch;
1018 0 : dst_ptr += dst_pitch;
1019 0 : } while (height > 0);
1020 0 : }
1021 :
1022 0 : static void aom_highbd_filter_block1d16_v2_avg_avx2(
1023 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
1024 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
1025 : __m256i signal[3], res0, res1;
1026 0 : const __m256i max = _mm256_set1_epi16((1 << bd) - 1);
1027 : __m256i ff;
1028 :
1029 0 : pack_2t_filter(filter, &ff);
1030 0 : pack_16x2_init(src_ptr, signal);
1031 :
1032 : do {
1033 0 : pack_16x2_2t_pixels(src_ptr, src_pitch, signal);
1034 0 : filter_16x2_2t_pixels(signal, &ff, &res0, &res1);
1035 0 : store_16x1_avg_pixels(&res0, &res1, &max, dst_ptr);
1036 :
1037 0 : src_ptr += src_pitch;
1038 0 : dst_ptr += dst_pitch;
1039 0 : height -= 1;
1040 0 : } while (height > 0);
1041 0 : }
1042 :
1043 0 : static void aom_highbd_filter_block1d8_v2_avg_avx2(
1044 : const uint16_t *src_ptr, ptrdiff_t src_pitch, uint16_t *dst_ptr,
1045 : ptrdiff_t dst_pitch, uint32_t height, const int16_t *filter, int bd) {
1046 : __m128i signal[3], res0, res1;
1047 0 : const __m128i max = _mm_set1_epi16((1 << bd) - 1);
1048 : __m128i ff;
1049 :
1050 0 : pack_8x1_2t_filter(filter, &ff);
1051 0 : pack_8x2_init(src_ptr, signal);
1052 :
1053 : do {
1054 0 : pack_8x2_2t_pixels_ver(src_ptr, src_pitch, signal);
1055 0 : filter_8_2t_pixels(signal, &ff, &res0, &res1);
1056 0 : store_8x1_2t_avg_pixels_ver(&res0, &res1, &max, dst_ptr);
1057 :
1058 0 : src_ptr += src_pitch;
1059 0 : dst_ptr += dst_pitch;
1060 0 : height -= 1;
1061 0 : } while (height > 0);
1062 0 : }
1063 :
1064 : void aom_highbd_filter_block1d4_h8_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
1065 : ptrdiff_t, uint32_t, const int16_t *,
1066 : int);
1067 : void aom_highbd_filter_block1d4_h2_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
1068 : ptrdiff_t, uint32_t, const int16_t *,
1069 : int);
1070 : void aom_highbd_filter_block1d4_v8_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
1071 : ptrdiff_t, uint32_t, const int16_t *,
1072 : int);
1073 : void aom_highbd_filter_block1d4_v2_sse2(const uint16_t *, ptrdiff_t, uint16_t *,
1074 : ptrdiff_t, uint32_t, const int16_t *,
1075 : int);
1076 : #define aom_highbd_filter_block1d4_h8_avx2 aom_highbd_filter_block1d4_h8_sse2
1077 : #define aom_highbd_filter_block1d4_h2_avx2 aom_highbd_filter_block1d4_h2_sse2
1078 : #define aom_highbd_filter_block1d4_v8_avx2 aom_highbd_filter_block1d4_v8_sse2
1079 : #define aom_highbd_filter_block1d4_v2_avx2 aom_highbd_filter_block1d4_v2_sse2
1080 :
1081 0 : HIGH_FUN_CONV_1D(horiz, x_step_q4, filter_x, h, src, , avx2);
1082 0 : HIGH_FUN_CONV_1D(vert, y_step_q4, filter_y, v, src - src_stride * 3, , avx2);
1083 0 : HIGH_FUN_CONV_2D(, avx2);
1084 :
1085 : void aom_highbd_filter_block1d4_h8_avg_sse2(const uint16_t *, ptrdiff_t,
1086 : uint16_t *, ptrdiff_t, uint32_t,
1087 : const int16_t *, int);
1088 : void aom_highbd_filter_block1d4_h2_avg_sse2(const uint16_t *, ptrdiff_t,
1089 : uint16_t *, ptrdiff_t, uint32_t,
1090 : const int16_t *, int);
1091 : void aom_highbd_filter_block1d4_v8_avg_sse2(const uint16_t *, ptrdiff_t,
1092 : uint16_t *, ptrdiff_t, uint32_t,
1093 : const int16_t *, int);
1094 : void aom_highbd_filter_block1d4_v2_avg_sse2(const uint16_t *, ptrdiff_t,
1095 : uint16_t *, ptrdiff_t, uint32_t,
1096 : const int16_t *, int);
1097 : #define aom_highbd_filter_block1d4_h8_avg_avx2 \
1098 : aom_highbd_filter_block1d4_h8_avg_sse2
1099 : #define aom_highbd_filter_block1d4_h2_avg_avx2 \
1100 : aom_highbd_filter_block1d4_h2_avg_sse2
1101 : #define aom_highbd_filter_block1d4_v8_avg_avx2 \
1102 : aom_highbd_filter_block1d4_v8_avg_sse2
1103 : #define aom_highbd_filter_block1d4_v2_avg_avx2 \
1104 : aom_highbd_filter_block1d4_v2_avg_sse2
1105 :
1106 0 : HIGH_FUN_CONV_1D(avg_horiz, x_step_q4, filter_x, h, src, avg_, avx2);
1107 0 : HIGH_FUN_CONV_1D(avg_vert, y_step_q4, filter_y, v, src - src_stride * 3, avg_,
1108 : avx2);
1109 0 : HIGH_FUN_CONV_2D(avg_, avx2);
1110 :
1111 : #undef HIGHBD_FUNC
|