Commit 0f80b1f7 authored by Yi Luo's avatar Yi Luo

Optimized HBD block subtraction for all block sizes

- Interface function takes a local MxN function to call based on the
  block size.
- Repetition call (w/o cache line miss) shows improvement:
  ~63% - ~340%.
- Overall encoder speed improvement: ~0.9%.

Change-Id: Ieff8f3d192415c61d6d58d8b99bb2a722004823f
parent f0290cd1
......@@ -15,12 +15,16 @@
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#if CONFIG_VP10
#include "vp10/common/blockd.h"
#elif CONFIG_VP9
#include "vp9/common/vp9_blockd.h"
#endif
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
#define USE_SPEED_TEST (0)
typedef void (*SubtractFunc)(int rows, int cols,
int16_t *diff_ptr, ptrdiff_t diff_stride,
......@@ -108,4 +112,151 @@ INSTANTIATE_TEST_CASE_P(NEON, VP9SubtractBlockTest,
INSTANTIATE_TEST_CASE_P(MSA, VP9SubtractBlockTest,
::testing::Values(vpx_subtract_block_msa));
#endif
typedef void (*HBDSubtractFunc)(int rows, int cols,
int16_t *diff_ptr, ptrdiff_t diff_stride,
const uint8_t *src_ptr, ptrdiff_t src_stride,
const uint8_t *pred_ptr, ptrdiff_t pred_stride,
int bd);
using ::std::tr1::get;
using ::std::tr1::make_tuple;
using ::std::tr1::tuple;
// <width, height, bit_dpeth, subtract>
typedef tuple<int, int, int, HBDSubtractFunc> Params;
#if CONFIG_VP9_HIGHBITDEPTH
class VP10HBDSubtractBlockTest : public ::testing::TestWithParam<Params> {
public:
virtual void SetUp() {
block_width_ = GET_PARAM(0);
block_height_ = GET_PARAM(1);
bit_depth_ = static_cast<vpx_bit_depth_t>(GET_PARAM(2));
func_ = GET_PARAM(3);
rnd_.Reset(ACMRandom::DeterministicSeed());
const size_t max_width = 128;
const size_t max_block_size = max_width * max_width;
src_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
vpx_memalign(16, max_block_size * sizeof(uint16_t))));
pred_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
vpx_memalign(16, max_block_size * sizeof(uint16_t))));
diff_ = reinterpret_cast<int16_t *>(
vpx_memalign(16, max_block_size * sizeof(int16_t)));
}
virtual void TearDown() {
vpx_free(CONVERT_TO_SHORTPTR(src_));
vpx_free(CONVERT_TO_SHORTPTR(pred_));
vpx_free(diff_);
}
protected:
void RunForSpeed();
void CheckResult();
private:
ACMRandom rnd_;
int block_height_;
int block_width_;
vpx_bit_depth_t bit_depth_;
HBDSubtractFunc func_;
uint8_t *src_;
uint8_t *pred_;
int16_t *diff_;
};
void VP10HBDSubtractBlockTest::RunForSpeed() {
const int test_num = 200000;
const int max_width = 128;
const int max_block_size = max_width * max_width;
const int mask = (1 << bit_depth_) - 1;
int i, j;
for (j = 0; j < max_block_size; ++j) {
CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask;
CONVERT_TO_SHORTPTR(pred_)[j] = rnd_.Rand16() & mask;
}
for (i = 0; i < test_num; ++i) {
func_(block_height_, block_width_, diff_, block_width_,
src_, block_width_, pred_, block_width_, bit_depth_);
}
}
void VP10HBDSubtractBlockTest::CheckResult() {
const int test_num = 100;
const int max_width = 128;
const int max_block_size = max_width * max_width;
const int mask = (1 << bit_depth_) - 1;
int i, j;
for (i = 0; i < test_num; ++i) {
for (j = 0; j < max_block_size; ++j) {
CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask;
CONVERT_TO_SHORTPTR(pred_)[j] = rnd_.Rand16() & mask;
}
func_(block_height_, block_width_, diff_, block_width_,
src_, block_width_, pred_, block_width_, bit_depth_);
for (int r = 0; r < block_height_; ++r) {
for (int c = 0; c < block_width_; ++c) {
EXPECT_EQ(diff_[r * block_width_ + c],
(CONVERT_TO_SHORTPTR(src_)[r * block_width_ + c] -
CONVERT_TO_SHORTPTR(pred_)[r * block_width_ + c]))
<< "r = " << r << ", c = " << c << ", test: " << i;
}
}
}
}
TEST_P(VP10HBDSubtractBlockTest, CheckResult) {
CheckResult();
}
#if USE_SPEED_TEST
TEST_P(VP10HBDSubtractBlockTest, CheckSpeed) {
RunForSpeed();
}
#endif // USE_SPEED_TEST
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, VP10HBDSubtractBlockTest, ::testing::Values(
make_tuple(4, 4, 12, vpx_highbd_subtract_block_sse2),
make_tuple(4, 4, 12, vpx_highbd_subtract_block_c),
make_tuple(4, 8, 12, vpx_highbd_subtract_block_sse2),
make_tuple(4, 8, 12, vpx_highbd_subtract_block_c),
make_tuple(8, 4, 12, vpx_highbd_subtract_block_sse2),
make_tuple(8, 4, 12, vpx_highbd_subtract_block_c),
make_tuple(8, 8, 12, vpx_highbd_subtract_block_sse2),
make_tuple(8, 8, 12, vpx_highbd_subtract_block_c),
make_tuple(8, 16, 12, vpx_highbd_subtract_block_sse2),
make_tuple(8, 16, 12, vpx_highbd_subtract_block_c),
make_tuple(16, 8, 12, vpx_highbd_subtract_block_sse2),
make_tuple(16, 8, 12, vpx_highbd_subtract_block_c),
make_tuple(16, 16, 12, vpx_highbd_subtract_block_sse2),
make_tuple(16, 16, 12, vpx_highbd_subtract_block_c),
make_tuple(16, 32, 12, vpx_highbd_subtract_block_sse2),
make_tuple(16, 32, 12, vpx_highbd_subtract_block_c),
make_tuple(32, 16, 12, vpx_highbd_subtract_block_sse2),
make_tuple(32, 16, 12, vpx_highbd_subtract_block_c),
make_tuple(32, 32, 12, vpx_highbd_subtract_block_sse2),
make_tuple(32, 32, 12, vpx_highbd_subtract_block_c),
make_tuple(32, 64, 12, vpx_highbd_subtract_block_sse2),
make_tuple(32, 64, 12, vpx_highbd_subtract_block_c),
make_tuple(64, 32, 12, vpx_highbd_subtract_block_sse2),
make_tuple(64, 32, 12, vpx_highbd_subtract_block_c),
make_tuple(64, 64, 12, vpx_highbd_subtract_block_sse2),
make_tuple(64, 64, 12, vpx_highbd_subtract_block_c),
make_tuple(64, 128, 12, vpx_highbd_subtract_block_sse2),
make_tuple(64, 128, 12, vpx_highbd_subtract_block_c),
make_tuple(128, 64, 12, vpx_highbd_subtract_block_sse2),
make_tuple(128, 64, 12, vpx_highbd_subtract_block_c),
make_tuple(128, 128, 12, vpx_highbd_subtract_block_sse2),
make_tuple(128, 128, 12, vpx_highbd_subtract_block_c)));
#endif // HAVE_SSE2
#endif // CONFIG_VP9_HIGHBITDEPTH
} // namespace
......@@ -266,6 +266,11 @@ DSP_SRCS-$(HAVE_SSSE3) += x86/avg_ssse3_x86_64.asm
endif
endif
# high bit depth subtract
ifeq ($(CONFIG_VP9_HIGHBITDEPTH),yes)
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_subtract_sse2.c
endif
endif # CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
ifeq ($(CONFIG_VP10_ENCODER),yes)
......
......@@ -965,10 +965,6 @@ if (vpx_config("CONFIG_ENCODERS") eq "yes") {
#
add_proto qw/void vpx_subtract_block/, "int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride";
specialize qw/vpx_subtract_block neon msa/, "$sse2_x86inc";
if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
add_proto qw/void vpx_highbd_subtract_block/, "int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride, int bd";
specialize qw/vpx_highbd_subtract_block/;
}
if (vpx_config("CONFIG_VP10_ENCODER") eq "yes") {
#
......@@ -991,6 +987,8 @@ if ((vpx_config("CONFIG_VP9_ENCODER") eq "yes") || (vpx_config("CONFIG_VP10_ENCO
specialize qw/vpx_highbd_avg_8x8/;
add_proto qw/unsigned int vpx_highbd_avg_4x4/, "const uint8_t *, int p";
specialize qw/vpx_highbd_avg_4x4/;
add_proto qw/void vpx_highbd_subtract_block/, "int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride, int bd";
specialize qw/vpx_highbd_subtract_block sse2/;
}
#
......
This diff is collapsed.
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