Line data Source code
1 : /*
2 : * Copyright(c) 2019 Intel Corporation
3 : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 : */
5 :
6 : #include "EbDefinitions.h"
7 : #include "EbRestoration.h"
8 : #include <immintrin.h>
9 : #include<math.h>
10 :
11 103486000 : static INLINE void avx2_mul_epi16_epi32(__m256i *a, __m256i *b, __m256i *out) {
12 : __m256i a_32[2];
13 : __m256i b_32[2];
14 :
15 103486000 : a_32[0] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*a, 1));
16 103486000 : a_32[1] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*a, 0));
17 :
18 103486000 : b_32[0] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*b, 1));
19 103486000 : b_32[1] = _mm256_cvtepi16_epi32(_mm256_extracti128_si256(*b, 0));
20 :
21 103486000 : out[0] = _mm256_mullo_epi32(a_32[0], b_32[0]);
22 103486000 : out[1] = _mm256_mullo_epi32(a_32[1], b_32[1]);
23 103486000 : }
24 4800 : void get_proj_subspace_avx2(const uint8_t *src8, int width, int height,
25 : int src_stride, const uint8_t *dat8,
26 : int dat_stride, int use_highbitdepth,
27 : int32_t *flt0, int flt0_stride, int32_t *flt1,
28 : int flt1_stride, int *xq,
29 : const SgrParamsType *params) {
30 : int i, j;
31 4800 : double H[2][2] = { { 0, 0 }, { 0, 0 } };
32 4800 : double C[2] = { 0, 0 };
33 : double Det;
34 : double x[2];
35 4800 : const int size = width * height;
36 :
37 4800 : aom_clear_system_state();
38 4800 : RunEmms();
39 :
40 : // Default
41 4800 : xq[0] = 0;
42 4800 : xq[1] = 0;
43 :
44 : __m256i H_00, H_01, H_11;
45 : __m256i C_0, C_1;
46 4800 : H_00 = _mm256_setzero_si256();
47 4800 : H_01 = _mm256_setzero_si256();
48 4800 : H_11 = _mm256_setzero_si256();
49 4800 : C_0 = _mm256_setzero_si256();
50 4800 : C_1 = _mm256_setzero_si256();
51 :
52 : __m256i u_256, s_256, f1_256, f2_256;
53 : __m256i f1_256_tmp, f2_256_tmp;
54 : __m256i out[2];
55 4800 : int avx2_cnt = 0;
56 :
57 4800 : if (!use_highbitdepth) {
58 4800 : const uint8_t *src = src8;
59 4800 : const uint8_t *dat = dat8;
60 1379910 : for (i = 0; i < height; ++i) {
61 22096000 : for (j = 0, avx2_cnt = 0; avx2_cnt < width / 16; j += 16, ++avx2_cnt) {
62 41441900 : u_256 = _mm256_cvtepu8_epi16(_mm_loadu_si128(
63 20720900 : (const __m128i *)(dat + i * dat_stride + j)));
64 20720900 : u_256 = _mm256_slli_epi16(u_256, SGRPROJ_RST_BITS);
65 :
66 20720900 : s_256 = _mm256_cvtepu8_epi16(_mm_loadu_si128(
67 20720900 : (const __m128i *)(src + i * src_stride + j)));
68 20720900 : s_256 = _mm256_slli_epi16(s_256, SGRPROJ_RST_BITS);
69 20720900 : s_256 = _mm256_sub_epi16(s_256, u_256);
70 :
71 20720900 : if (params->r[0] > 0) {
72 15544100 : f1_256 = _mm256_loadu_si256(
73 15544100 : (const __m256i *)(flt0 + i * flt0_stride + j));
74 15544100 : f1_256_tmp = _mm256_loadu_si256(
75 15544100 : (const __m256i *)(flt0 + i * flt0_stride + j + 8));
76 :
77 15544100 : f1_256 = _mm256_hadd_epi16(f1_256, f1_256_tmp);
78 15544100 : f1_256 = _mm256_permute4x64_epi64(f1_256, 0xD8);
79 31088100 : f1_256 = _mm256_sub_epi16(f1_256, u_256);
80 : } else
81 5176880 : f1_256 = _mm256_set1_epi16(0);
82 20720900 : if (params->r[1] > 0) {
83 18134000 : f2_256 = _mm256_loadu_si256(
84 18134000 : (const __m256i *)(flt1 + i * flt1_stride + j));
85 18134000 : f2_256_tmp = _mm256_loadu_si256(
86 18134000 : (const __m256i *)(flt1 + i * flt1_stride + j + 8));
87 :
88 18134000 : f2_256 = _mm256_hadd_epi16(f2_256, f2_256_tmp);
89 18134000 : f2_256 = _mm256_permute4x64_epi64(f2_256, 0xD8);
90 36268000 : f2_256 = _mm256_sub_epi16(f2_256, u_256);
91 : } else
92 2586940 : f2_256 = _mm256_set1_epi16(0);
93 : // H[0][0] += f1 * f1;
94 20720900 : avx2_mul_epi16_epi32(&f1_256, &f1_256, out);
95 20722100 : H_00 = _mm256_add_epi32(H_00, out[0]);
96 20722100 : H_00 = _mm256_add_epi32(H_00, out[1]);
97 :
98 : // H[1][1] += f2 * f2;
99 20722100 : avx2_mul_epi16_epi32(&f2_256, &f2_256, out);
100 20720000 : H_11 = _mm256_add_epi32(H_11, out[0]);
101 20720000 : H_11 = _mm256_add_epi32(H_11, out[1]);
102 : // H[0][1] += f1 * f2;
103 20720000 : avx2_mul_epi16_epi32(&f1_256, &f2_256, out);
104 20714200 : H_01 = _mm256_add_epi32(H_01, out[0]);
105 20714200 : H_01 = _mm256_add_epi32(H_01, out[1]);
106 :
107 : // C[0] += f1 * s;
108 20714200 : avx2_mul_epi16_epi32(&f1_256, &s_256, out);
109 20713900 : C_0 = _mm256_add_epi32(C_0, out[0]);
110 20713900 : C_0 = _mm256_add_epi32(C_0, out[1]);
111 :
112 : // C[1] += f2 * s;
113 20713900 : avx2_mul_epi16_epi32(&f2_256, &s_256, out);
114 20713700 : C_1 = _mm256_add_epi32(C_1, out[0]);
115 41427300 : C_1 = _mm256_add_epi32(C_1, out[1]);
116 : }
117 :
118 : //Complement when width not divided by 16
119 1375110 : for (; j < width; ++j) {
120 0 : const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
121 0 : const double s =
122 0 : (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
123 0 : const double f1 =
124 0 : (params->r[0] > 0) ? (double)flt0[i * flt0_stride + j] - u : 0;
125 0 : const double f2 =
126 0 : (params->r[1] > 0) ? (double)flt1[i * flt1_stride + j] - u : 0;
127 0 : H[0][0] += f1 * f1;
128 0 : H[1][1] += f2 * f2;
129 0 : H[0][1] += f1 * f2;
130 0 : C[0] += f1 * s;
131 0 : C[1] += f2 * s;
132 : }
133 :
134 : //Summary in each row, to not overflow 32 bits value H_
135 1375110 : H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,1,4,5
136 1375110 : H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,4
137 1375110 : H[0][0] += (double)_mm256_extract_epi32(H_00, 0) +
138 1375110 : _mm256_extract_epi32(H_00, 4);
139 :
140 1375110 : H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,1,4,5
141 1375110 : H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,4
142 1375110 : H[1][1] += (double)_mm256_extract_epi32(H_11, 0) +
143 1375110 : _mm256_extract_epi32(H_11, 4);
144 :
145 1375110 : H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,1,4,5
146 1375110 : H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,4
147 1375110 : H[0][1] += (double)_mm256_extract_epi32(H_01, 0) +
148 1375110 : _mm256_extract_epi32(H_01, 4);
149 :
150 1375110 : C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,1,4,5
151 1375110 : C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,4
152 1375110 : C[0] += (double)_mm256_extract_epi32(C_0, 0) +
153 1375110 : _mm256_extract_epi32(C_0, 4);
154 :
155 1375110 : C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,1,4,5
156 1375110 : C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,4
157 1375110 : C[1] += (double)_mm256_extract_epi32(C_1, 0) +
158 1375110 : _mm256_extract_epi32(C_1, 4);
159 :
160 1375110 : H_00 = _mm256_setzero_si256();
161 1375110 : H_01 = _mm256_setzero_si256();
162 1375110 : H_11 = _mm256_setzero_si256();
163 1375110 : C_0 = _mm256_setzero_si256();
164 1375110 : C_1 = _mm256_setzero_si256();
165 : }
166 : } else {
167 0 : const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
168 0 : const uint16_t *dat = CONVERT_TO_SHORTPTR(dat8);
169 :
170 0 : for (i = 0; i < height; ++i) {
171 0 : for (j = 0, avx2_cnt = 0; avx2_cnt < width / 16; j += 16, ++avx2_cnt) {
172 0 : u_256 = _mm256_loadu_si256(
173 0 : (const __m256i *)(dat + i * dat_stride + j));
174 0 : u_256 = _mm256_slli_epi16(u_256, SGRPROJ_RST_BITS);
175 :
176 0 : s_256 = _mm256_loadu_si256(
177 0 : (const __m256i *)(src + i * src_stride + j));
178 0 : s_256 = _mm256_slli_epi16(s_256, SGRPROJ_RST_BITS);
179 0 : s_256 = _mm256_sub_epi16(s_256, u_256);
180 :
181 0 : if (params->r[0] > 0) {
182 0 : f1_256 = _mm256_loadu_si256(
183 0 : (const __m256i *)(flt0 + i * flt0_stride + j));
184 0 : f1_256_tmp = _mm256_loadu_si256(
185 0 : (const __m256i *)(flt0 + i * flt0_stride + j + 8));
186 :
187 0 : f1_256 = _mm256_hadd_epi16(f1_256, f1_256_tmp);
188 0 : f1_256 = _mm256_permute4x64_epi64(f1_256, 0xD8);
189 0 : f1_256 = _mm256_sub_epi16(f1_256, u_256);
190 : } else
191 0 : f1_256 = _mm256_set1_epi16(0);
192 0 : if (params->r[1] > 0) {
193 0 : f2_256 = _mm256_loadu_si256(
194 0 : (const __m256i *)(flt1 + i * flt1_stride + j));
195 0 : f2_256_tmp = _mm256_loadu_si256(
196 0 : (const __m256i *)(flt1 + i * flt1_stride + j + 8));
197 :
198 0 : f2_256 = _mm256_hadd_epi16(f2_256, f2_256_tmp);
199 0 : f2_256 = _mm256_permute4x64_epi64(f2_256, 0xD8);
200 0 : f2_256 = _mm256_sub_epi16(f2_256, u_256);
201 : } else
202 0 : f2_256 = _mm256_set1_epi16(0);
203 : // H[0][0] += f1 * f1;
204 0 : avx2_mul_epi16_epi32(&f1_256, &f1_256, out);
205 0 : H_00 = _mm256_add_epi32(H_00, out[0]);
206 0 : H_00 = _mm256_add_epi32(H_00, out[1]);
207 :
208 : // H[1][1] += f2 * f2;
209 0 : avx2_mul_epi16_epi32(&f2_256, &f2_256, out);
210 0 : H_11 = _mm256_add_epi32(H_11, out[0]);
211 0 : H_11 = _mm256_add_epi32(H_11, out[1]);
212 : // H[0][1] += f1 * f2;
213 0 : avx2_mul_epi16_epi32(&f1_256, &f2_256, out);
214 0 : H_01 = _mm256_add_epi32(H_01, out[0]);
215 0 : H_01 = _mm256_add_epi32(H_01, out[1]);
216 :
217 : // C[0] += f1 * s;
218 0 : avx2_mul_epi16_epi32(&f1_256, &s_256, out);
219 0 : C_0 = _mm256_add_epi32(C_0, out[0]);
220 0 : C_0 = _mm256_add_epi32(C_0, out[1]);
221 :
222 : // C[1] += f2 * s;
223 0 : avx2_mul_epi16_epi32(&f2_256, &s_256, out);
224 0 : C_1 = _mm256_add_epi32(C_1, out[0]);
225 0 : C_1 = _mm256_add_epi32(C_1, out[1]);
226 : }
227 :
228 : //Complement when width not divided by 16
229 0 : for (; j < width; ++j) {
230 0 : const double u = (double)(dat[i * dat_stride + j] << SGRPROJ_RST_BITS);
231 0 : const double s =
232 0 : (double)(src[i * src_stride + j] << SGRPROJ_RST_BITS) - u;
233 0 : const double f1 =
234 0 : (params->r[0] > 0) ? (double)flt0[i * flt0_stride + j] - u : 0;
235 0 : const double f2 =
236 0 : (params->r[1] > 0) ? (double)flt1[i * flt1_stride + j] - u : 0;
237 0 : H[0][0] += f1 * f1;
238 0 : H[1][1] += f2 * f2;
239 0 : H[0][1] += f1 * f2;
240 0 : C[0] += f1 * s;
241 0 : C[1] += f2 * s;
242 : }
243 :
244 : //Summary in each row, to not overflow 32 bits value H_
245 0 : H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,1,4,5
246 0 : H_00 = _mm256_hadd_epi32(H_00, H_00);//indexes 0,4
247 0 : H[0][0] += (double)_mm256_extract_epi32(H_00, 0) +
248 0 : _mm256_extract_epi32(H_00, 4);
249 :
250 0 : H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,1,4,5
251 0 : H_11 = _mm256_hadd_epi32(H_11, H_11);//indexes 0,4
252 0 : H[1][1] += (double)_mm256_extract_epi32(H_11, 0) +
253 0 : _mm256_extract_epi32(H_11, 4);
254 :
255 0 : H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,1,4,5
256 0 : H_01 = _mm256_hadd_epi32(H_01, H_01);//indexes 0,4
257 0 : H[0][1] += (double)_mm256_extract_epi32(H_01, 0) +
258 0 : _mm256_extract_epi32(H_01, 4);
259 :
260 0 : C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,1,4,5
261 0 : C_0 = _mm256_hadd_epi32(C_0, C_0);//indexes 0,4
262 0 : C[0] += (double)_mm256_extract_epi32(C_0, 0) +
263 0 : _mm256_extract_epi32(C_0, 4);
264 :
265 0 : C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,1,4,5
266 0 : C_1 = _mm256_hadd_epi32(C_1, C_1);//indexes 0,4
267 0 : C[1] += (double)_mm256_extract_epi32(C_1, 0) +
268 0 : _mm256_extract_epi32(C_1, 4);
269 :
270 0 : H_00 = _mm256_setzero_si256();
271 0 : H_01 = _mm256_setzero_si256();
272 0 : H_11 = _mm256_setzero_si256();
273 0 : C_0 = _mm256_setzero_si256();
274 0 : C_1 = _mm256_setzero_si256();
275 : }
276 : }
277 :
278 0 : H[0][0] /= size;
279 0 : H[0][1] /= size;
280 0 : H[1][1] /= size;
281 0 : H[1][0] = H[0][1];
282 0 : C[0] /= size;
283 0 : C[1] /= size;
284 0 : if (params->r[0] == 0) {
285 : // H matrix is now only the scalar H[1][1]
286 : // C vector is now only the scalar C[1]
287 1200 : Det = H[1][1];
288 1200 : if (Det < 1e-8) return; // ill-posed, return default values
289 1200 : x[0] = 0;
290 1200 : x[1] = C[1] / Det;
291 :
292 1200 : xq[0] = 0;
293 1200 : xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
294 0 : } else if (params->r[1] == 0) {
295 : // H matrix is now only the scalar H[0][0]
296 : // C vector is now only the scalar C[0]
297 600 : Det = H[0][0];
298 600 : if (Det < 1e-8) return; // ill-posed, return default values
299 600 : x[0] = C[0] / Det;
300 600 : x[1] = 0;
301 :
302 600 : xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
303 600 : xq[1] = 0;
304 : } else {
305 0 : Det = (H[0][0] * H[1][1] - H[0][1] * H[1][0]);
306 0 : if (Det < 1e-8) return; // ill-posed, return default values
307 0 : x[0] = (H[1][1] * C[0] - H[0][1] * C[1]) / Det;
308 0 : x[1] = (H[0][0] * C[1] - H[1][0] * C[0]) / Det;
309 :
310 0 : xq[0] = (int)rint(x[0] * (1 << SGRPROJ_PRJ_BITS));
311 0 : xq[1] = (int)rint(x[1] * (1 << SGRPROJ_PRJ_BITS));
312 : }
313 : }
|