Commit 57e41ea6 authored by Yunqing Wang's avatar Yunqing Wang

Convolve copy function optimization

Added a copy function (c version and sse2 version) for full-pixel motion
vectors. Here, the compound or non-compound cases were not separated, and
the left shifting were always done.

Change-Id: Idb13e7c0576503a434d0d6e926cd54db645a4ff9
parent 891a8774
......@@ -570,6 +570,11 @@ if (aom_config("CONFIG_CONVOLVE_ROUND") eq "yes") {
add_proto qw/void av1_convolve_rounding/, "const int32_t *src, int src_stride, uint8_t *dst, int dst_stride, int w, int h, int bits";
specialize qw/av1_convolve_rounding avx2/;
if (aom_config("CONFIG_COMPOUND_ROUND") ne "yes") {
add_proto qw/void av1_convolve_2d_copy/, "const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride, int w, int h, InterpFilterParams *filter_params_x, InterpFilterParams *filter_params_y, const int subpel_x_q4, const int subpel_y_q4, ConvolveParams *conv_params";
specialize qw/av1_convolve_2d_copy sse2/;
}
add_proto qw/void av1_convolve_2d_scale/, "const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride, int w, int h, InterpFilterParams *filter_params_x, InterpFilterParams *filter_params_y, const int subpel_x_qn, const int x_step_qn, const int subpel_y_q4, const int y_step_qn, ConvolveParams *conv_params";
if (aom_config("CONFIG_COMPOUND_ROUND") ne "yes") {
specialize qw/av1_convolve_2d_scale sse4_1/;
......
......@@ -623,6 +623,31 @@ void av1_convolve_2d_c(const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst,
}
}
void av1_convolve_2d_copy_c(const uint8_t *src, int src_stride,
CONV_BUF_TYPE *dst, int dst_stride, int w, int h,
InterpFilterParams *filter_params_x,
InterpFilterParams *filter_params_y,
const int subpel_x_q4, const int subpel_y_q4,
ConvolveParams *conv_params) {
const int bits =
FILTER_BITS * 2 - conv_params->round_1 - conv_params->round_0;
int x, y;
(void)filter_params_x;
(void)filter_params_y;
(void)subpel_x_q4;
(void)subpel_y_q4;
for (y = 0; y < h; ++y) {
for (x = 0; x < w; ++x) {
CONV_BUF_TYPE res = (1 << bits) * src[y * src_stride + x];
if (conv_params->do_average)
dst[y * dst_stride + x] += res;
else
dst[y * dst_stride + x] = res;
}
}
}
#if CONFIG_JNT_COMP
void av1_jnt_convolve_2d_c(const uint8_t *src, int src_stride,
CONV_BUF_TYPE *dst, int dst_stride, int w, int h,
......@@ -846,15 +871,37 @@ void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst,
&filter_params_y, subpel_x_q4, subpel_y_q4,
conv_params);
#else
if (scaled)
if (scaled) {
av1_convolve_2d_scale(src, src_stride, conv_params->dst,
conv_params->dst_stride, w, h, &filter_params_x,
&filter_params_y, subpel_x_q4, x_step_q4,
subpel_y_q4, y_step_q4, conv_params);
else
} else {
#if CONFIG_COMPOUND_ROUND
av1_convolve_2d(src, src_stride, conv_params->dst,
conv_params->dst_stride, w, h, &filter_params_x,
&filter_params_y, subpel_x_q4, subpel_y_q4, conv_params);
#else
if (subpel_x_q4 == 0 && subpel_y_q4 == 0) {
av1_convolve_2d_copy(src, src_stride, conv_params->dst,
conv_params->dst_stride, w, h, &filter_params_x,
&filter_params_y, subpel_x_q4, subpel_y_q4,
conv_params);
} else if (subpel_x_q4 == 0 || subpel_y_q4 == 0) {
// place holder
av1_convolve_2d(src, src_stride, conv_params->dst,
conv_params->dst_stride, w, h, &filter_params_x,
&filter_params_y, subpel_x_q4, subpel_y_q4,
conv_params);
} else {
// subpel_x_q4 != 0 && subpel_y_q4 != 0
av1_convolve_2d(src, src_stride, conv_params->dst,
conv_params->dst_stride, w, h, &filter_params_x,
&filter_params_y, subpel_x_q4, subpel_y_q4,
conv_params);
}
#endif // CONFIG_COMPOUND_ROUND
}
#endif // CONFIG_JNT_COMP
}
}
......
......@@ -378,4 +378,97 @@ void av1_convolve_2d_sse2(const uint8_t *src, int src_stride,
}
}
}
void av1_convolve_2d_copy_sse2(const uint8_t *src, int src_stride,
CONV_BUF_TYPE *dst, int dst_stride, int w, int h,
InterpFilterParams *filter_params_x,
InterpFilterParams *filter_params_y,
const int subpel_x_q4, const int subpel_y_q4,
ConvolveParams *conv_params) {
const int bits =
FILTER_BITS * 2 - conv_params->round_1 - conv_params->round_0;
const int do_average = conv_params->do_average;
const __m128i zero = _mm_setzero_si128();
const __m128i left_shift = _mm_cvtsi32_si128(bits);
int i, j;
(void)filter_params_x;
(void)filter_params_y;
(void)subpel_x_q4;
(void)subpel_y_q4;
if (!(w % 16)) {
for (i = 0; i < h; ++i) {
for (j = 0; j < w; j += 16) {
const __m128i d8 = _mm_loadu_si128((__m128i *)&src[j]);
const __m128i d16_0 = _mm_unpacklo_epi8(d8, zero);
const __m128i d16_1 = _mm_unpackhi_epi8(d8, zero);
__m128i d32_0 = _mm_unpacklo_epi16(d16_0, zero);
__m128i d32_1 = _mm_unpackhi_epi16(d16_0, zero);
__m128i d32_2 = _mm_unpacklo_epi16(d16_1, zero);
__m128i d32_3 = _mm_unpackhi_epi16(d16_1, zero);
d32_0 = _mm_sll_epi32(d32_0, left_shift);
d32_1 = _mm_sll_epi32(d32_1, left_shift);
d32_2 = _mm_sll_epi32(d32_2, left_shift);
d32_3 = _mm_sll_epi32(d32_3, left_shift);
__m128i *const p = (__m128i *)&dst[j];
if (do_average) {
_mm_storeu_si128(p + 0, _mm_add_epi32(_mm_loadu_si128(p + 0), d32_0));
_mm_storeu_si128(p + 1, _mm_add_epi32(_mm_loadu_si128(p + 1), d32_1));
_mm_storeu_si128(p + 2, _mm_add_epi32(_mm_loadu_si128(p + 2), d32_2));
_mm_storeu_si128(p + 3, _mm_add_epi32(_mm_loadu_si128(p + 3), d32_3));
} else {
_mm_storeu_si128(p + 0, d32_0);
_mm_storeu_si128(p + 1, d32_1);
_mm_storeu_si128(p + 2, d32_2);
_mm_storeu_si128(p + 3, d32_3);
}
}
src += src_stride;
dst += dst_stride;
}
} else if (!(w % 8)) {
for (i = 0; i < h; ++i) {
for (j = 0; j < w; j += 8) {
const __m128i d8 = _mm_loadl_epi64((__m128i *)&src[j]);
const __m128i d16_0 = _mm_unpacklo_epi8(d8, zero);
__m128i d32_0 = _mm_unpacklo_epi16(d16_0, zero);
__m128i d32_1 = _mm_unpackhi_epi16(d16_0, zero);
d32_0 = _mm_sll_epi32(d32_0, left_shift);
d32_1 = _mm_sll_epi32(d32_1, left_shift);
__m128i *const p = (__m128i *)&dst[j];
if (do_average) {
_mm_storeu_si128(p + 0, _mm_add_epi32(_mm_loadu_si128(p + 0), d32_0));
_mm_storeu_si128(p + 1, _mm_add_epi32(_mm_loadu_si128(p + 1), d32_1));
} else {
_mm_storeu_si128(p + 0, d32_0);
_mm_storeu_si128(p + 1, d32_1);
}
}
src += src_stride;
dst += dst_stride;
}
} else {
for (i = 0; i < h; ++i) {
for (j = 0; j < w; j += 2) {
const __m128i d8 = _mm_cvtsi32_si128(*(const int *)&src[j]);
const __m128i d16_0 = _mm_unpacklo_epi8(d8, zero);
__m128i d32_0 = _mm_unpacklo_epi16(d16_0, zero);
d32_0 = _mm_sll_epi32(d32_0, left_shift);
__m128i *const p = (__m128i *)&dst[j];
if (do_average) {
_mm_storel_epi64(p, _mm_add_epi32(_mm_loadl_epi64(p), d32_0));
} else {
_mm_storel_epi64(p, d32_0);
}
}
src += src_stride;
dst += dst_stride;
}
}
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment