Utilize registers more efficiently for 8x8 and larger blocks

This commit is contained in:
Ari Lemmetti 2016-04-20 11:00:19 +03:00
parent 192cee95b2
commit efbdc5dade

View file

@ -34,6 +34,7 @@
#include "strategies/generic/picture-generic.h"
#include "strategies/strategies-ipol.h"
#include "strategyselector.h"
#include "strategies/strategies-common.h"
#define FILTER_OFFSET 3
@ -267,6 +268,22 @@ void kvz_four_tap_filter_x4_hor_avx2(int8_t *filter, kvz_pixel *data, int shift,
_mm_storel_epi64((__m128i*)dst, temp);
}
void kvz_four_tap_filter_x8_hor_avx2(int8_t *filter, kvz_pixel *data, int shift, int16_t* dst)
{
__m256i packed_data = _mm256_inserti128_si256(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)data)), _mm_loadl_epi64((__m128i*)(data + 4)), 1);
__m256i packed_filter = _mm256_set1_epi32(*(int32_t*)filter);
__m256i idx_lookup = _mm256_broadcastsi128_si256(_mm_setr_epi8(0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6));
__m256i temp = _mm256_shuffle_epi8(packed_data, idx_lookup);
temp = _mm256_maddubs_epi16(temp, packed_filter);
temp = _mm256_hadd_epi16(temp, temp);
temp = _mm256_srai_epi16(temp, shift);
_mm_storel_epi64((__m128i*)dst, _mm256_castsi256_si128(temp));
_mm_storel_epi64((__m128i*)(dst + 4), _mm256_extracti128_si256(temp, 1));
}
int32_t kvz_four_tap_filter_x4_ver_16bit_avx2(int8_t *filter, int16_t *data, int16_t stride, int offset, int shift2, int shift3)
{
@ -291,6 +308,31 @@ int32_t kvz_four_tap_filter_x4_ver_16bit_avx2(int8_t *filter, int16_t *data, int
return _mm_cvtsi128_si32(temp);
}
void kvz_four_tap_filter_x8_ver_16bit_avx2(int8_t *filter, int16_t *data, int16_t stride, int offset, int shift2, int shift3, kvz_pixel* dst)
{
__m256i v_filter = _mm256_cvtepi8_epi16(_mm_set1_epi16(*(int16_t*)&(filter[0])));
__m256i v_data0 = _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)(data + stride * 0)));
__m256i v_data1 = _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)(data + stride * 1)));
__m256i v_data = _mm256_or_si256(v_data0, _mm256_slli_epi32(v_data1, 16));
__m256i temp = _mm256_madd_epi16(v_filter, v_data);
v_filter = _mm256_cvtepi8_epi16(_mm_set1_epi16(*(int16_t*)&(filter[2])));
__m256i v_data2 = _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)(data + stride * 2)));
__m256i v_data3 = _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)(data + stride * 3)));
v_data = _mm256_or_si256(v_data2, _mm256_slli_epi32(v_data3, 16));
temp = _mm256_add_epi32(temp, _mm256_madd_epi16(v_filter, v_data) );
temp = _mm256_add_epi32(temp, _mm256_set1_epi32(offset));
temp = _mm256_srai_epi32(temp, shift2 + shift3);
temp = _mm256_packus_epi32(temp, temp);
temp = _mm256_packus_epi16(temp, temp);
*(int32_t*)dst = _mm_cvtsi128_si32(_mm256_castsi256_si128(temp));
*(int32_t*)(dst + 4) = _mm_cvtsi128_si32(_mm256_extracti128_si256(temp, 1));
}
void kvz_filter_inter_quarterpel_luma_avx2(const encoder_control_t * const encoder, kvz_pixel *src, int16_t src_stride, int width, int height, kvz_pixel *dst, int16_t dst_stride, int8_t hor_flag, int8_t ver_flag)
{
@ -538,13 +580,14 @@ void kvz_sample_octpel_chroma_avx2(const encoder_control_t * const encoder, kvz_
#define FILTER_OFFSET_C (FILTER_OFFSET / 2)
int16_t hor_filtered[(LCU_WIDTH_C + 1) + FILTER_SIZE_C][(LCU_WIDTH_C + 1) + FILTER_SIZE_C];
if (width == 4) {
// Filter horizontally and flip x and y
for (y = 0; y < height + FILTER_SIZE_C - 1; ++y) {
for (x = 0; x < width; x += 4) {
int ypos = y - FILTER_OFFSET_C;
int xpos = x - FILTER_OFFSET_C;
int16_t *dst = &(hor_filtered[y][x]);
kvz_four_tap_filter_x4_hor_avx2(hor_filter, &src[src_stride*ypos + xpos], shift1, dst);
int16_t *out = &(hor_filtered[y][x]);
kvz_four_tap_filter_x4_hor_avx2(hor_filter, &src[src_stride*ypos + xpos], shift1, out);
}
}
@ -556,6 +599,28 @@ void kvz_sample_octpel_chroma_avx2(const encoder_control_t * const encoder, kvz_
*(int32_t*)&(dst[y*dst_stride + x]) = kvz_four_tap_filter_x4_ver_16bit_avx2(ver_filter, &hor_filtered[ypos][xpos], sizeof(hor_filtered[0])/sizeof(int16_t), offset23, shift2, shift3);
}
}
} else {
// Filter horizontally and flip x and y
for (y = 0; y < height + FILTER_SIZE_C - 1; ++y) {
for (x = 0; x < width; x += 8) {
int ypos = y - FILTER_OFFSET_C;
int xpos = x - FILTER_OFFSET_C;
int16_t *dst = &(hor_filtered[y][x]);
kvz_four_tap_filter_x8_hor_avx2(hor_filter, &src[src_stride*ypos + xpos], shift1, dst);
}
}
// Filter vertically and flip x and y
for (y = 0; y < height; ++y) {
for (x = 0; x < width; x+=8) {
int ypos = y;
int xpos = x;
kvz_pixel *out = &(dst[y*dst_stride + x]);
kvz_four_tap_filter_x8_ver_16bit_avx2(ver_filter, &hor_filtered[ypos][xpos], sizeof(hor_filtered[0])/sizeof(int16_t), offset23, shift2, shift3, out);
}
}
}
}