From 5aee8ea7523e6242094abb1f21e3df15107a83c7 Mon Sep 17 00:00:00 2001 From: Johann Date: Tue, 6 Jun 2017 15:15:47 -0700 Subject: [PATCH] buffer.h: allow declaring an alignment x86 simd register operations generally prefer and may require 16 byte alignment. Change-Id: I73ce577a90dc66af60743c5727c36f23200950ba --- test/buffer.h | 46 +++++++++++++++++++++---- test/comp_avg_pred_test.cc | 84 ++++++++++++++++++++++++++-------------------- 2 files changed, 87 insertions(+), 43 deletions(-) diff --git a/test/buffer.h b/test/buffer.h index 5058417..8fbab22 100644 --- a/test/buffer.h +++ b/test/buffer.h @@ -19,6 +19,7 @@ #include "test/acm_random.h" #include "vpx/vpx_integer.h" +#include "vpx_mem/vpx_mem.h" namespace libvpx_test { @@ -29,16 +30,36 @@ class Buffer { int right_padding, int bottom_padding) : width_(width), height_(height), top_padding_(top_padding), left_padding_(left_padding), right_padding_(right_padding), - bottom_padding_(bottom_padding), padding_value_(0), stride_(0), - raw_size_(0), num_elements_(0), raw_buffer_(NULL) {} + bottom_padding_(bottom_padding), alignment_(0), padding_value_(0), + stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(NULL) {} + + Buffer(int width, int height, int top_padding, int left_padding, + int right_padding, int bottom_padding, unsigned int alignment) + : width_(width), height_(height), top_padding_(top_padding), + left_padding_(left_padding), right_padding_(right_padding), + bottom_padding_(bottom_padding), alignment_(alignment), + padding_value_(0), stride_(0), raw_size_(0), num_elements_(0), + raw_buffer_(NULL) {} Buffer(int width, int height, int padding) : width_(width), height_(height), top_padding_(padding), left_padding_(padding), right_padding_(padding), - bottom_padding_(padding), padding_value_(0), stride_(0), raw_size_(0), - num_elements_(0), raw_buffer_(NULL) {} + bottom_padding_(padding), alignment_(0), padding_value_(0), stride_(0), + raw_size_(0), num_elements_(0), raw_buffer_(NULL) {} - ~Buffer() { delete[] raw_buffer_; } + Buffer(int width, int height, int padding, unsigned int alignment) + : width_(width), height_(height), top_padding_(padding), + left_padding_(padding), right_padding_(padding), + bottom_padding_(padding), alignment_(alignment), padding_value_(0), + stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(NULL) {} + + ~Buffer() { + if (alignment_) { + vpx_free(raw_buffer_); + } else { + delete[] raw_buffer_; + } + } T *TopLeftPixel() const; @@ -82,8 +103,20 @@ class Buffer { EXPECT_GE(bottom_padding_, 0); stride_ = left_padding_ + width_ + right_padding_; num_elements_ = stride_ * (top_padding_ + height_ + bottom_padding_); - raw_buffer_ = new (std::nothrow) T[num_elements_]; raw_size_ = num_elements_ * sizeof(T); + if (alignment_) { + EXPECT_GE(alignment_, sizeof(T)); + // Ensure alignment of the first value will be preserved. + EXPECT_EQ((left_padding_ * sizeof(T)) % alignment_, 0u); + // Ensure alignment of the subsequent rows will be preserved when there is + // a stride. + if (stride_ != width_) { + EXPECT_EQ((stride_ * sizeof(T)) % alignment_, 0u); + } + raw_buffer_ = reinterpret_cast(vpx_memalign(alignment_, raw_size_)); + } else { + raw_buffer_ = new (std::nothrow) T[num_elements_]; + } EXPECT_TRUE(raw_buffer_ != NULL); SetPadding(std::numeric_limits::max()); return !::testing::Test::HasFailure(); @@ -98,6 +131,7 @@ class Buffer { const int left_padding_; const int right_padding_; const int bottom_padding_; + const unsigned int alignment_; T padding_value_; int stride_; int raw_size_; diff --git a/test/comp_avg_pred_test.cc b/test/comp_avg_pred_test.cc index 3c1d746..110e065 100644 --- a/test/comp_avg_pred_test.cc +++ b/test/comp_avg_pred_test.cc @@ -15,7 +15,6 @@ #include "test/acm_random.h" #include "test/buffer.h" #include "test/register_state_check.h" -#include "vpx_ports/mem.h" #include "vpx_ports/vpx_timer.h" namespace { @@ -28,12 +27,13 @@ typedef void (*AvgPredFunc)(uint8_t *a, const uint8_t *b, int w, int h, uint8_t avg_with_rounding(uint8_t a, uint8_t b) { return (a + b + 1) >> 1; } -void reference_pred(const uint8_t *pred, const Buffer &ref, int width, - int height, uint8_t *avg) { +void reference_pred(const Buffer &pred, const Buffer &ref, + int width, int height, Buffer *avg) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { - avg[y * width + x] = avg_with_rounding( - pred[y * width + x], ref.TopLeftPixel()[y * ref.stride() + x]); + avg->TopLeftPixel()[y * avg->stride() + x] = + avg_with_rounding(pred.TopLeftPixel()[y * pred.stride() + x], + ref.TopLeftPixel()[y * ref.stride() + x]); } } } @@ -50,22 +50,10 @@ class AvgPredTest : public ::testing::TestWithParam { ACMRandom rnd_; }; -void fill(ACMRandom *r, uint8_t *a, const int width, const int height) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - a[x + width * y] = r->Rand8(); - } - } -} - TEST_P(AvgPredTest, SizeCombinations) { // This is called as part of the sub pixel variance. As such it must be one of // the variance block sizes. - DECLARE_ALIGNED(16, uint8_t, pred[64 * 64]); - DECLARE_ALIGNED(16, uint8_t, avg_ref[64 * 64]); - DECLARE_ALIGNED(16, uint8_t, avg_chk[64 * 64]); - for (int width_pow = 2; width_pow <= 6; ++width_pow) { for (int height_pow = width_pow - 1; height_pow <= width_pow + 1; ++height_pow) { @@ -81,15 +69,27 @@ TEST_P(AvgPredTest, SizeCombinations) { Buffer ref = Buffer(width, height, ref_padding ? 8 : 0); ASSERT_TRUE(ref.Init()); + Buffer pred = Buffer(width, height, 0, 16); + ASSERT_TRUE(pred.Init()); + Buffer avg_ref = Buffer(width, height, 0, 16); + ASSERT_TRUE(avg_ref.Init()); + Buffer avg_chk = Buffer(width, height, 0, 16); + ASSERT_TRUE(avg_chk.Init()); - fill(&rnd_, pred, width, height); ref.Set(&rnd_, &ACMRandom::Rand8); - - reference_pred(pred, ref, width, height, avg_ref); - ASM_REGISTER_STATE_CHECK(avg_pred_func_( - avg_chk, pred, width, height, ref.TopLeftPixel(), ref.stride())); - ASSERT_EQ(memcmp(avg_ref, avg_chk, sizeof(*avg_ref) * width * height), - 0); + pred.Set(&rnd_, &ACMRandom::Rand8); + + reference_pred(pred, ref, width, height, &avg_ref); + ASM_REGISTER_STATE_CHECK( + avg_pred_func_(avg_chk.TopLeftPixel(), pred.TopLeftPixel(), width, + height, ref.TopLeftPixel(), ref.stride())); + + EXPECT_TRUE(avg_chk.CheckValues(avg_ref)); + if (HasFailure()) { + printf("Width: %d Height: %d\n", width, height); + avg_chk.PrintDifference(avg_ref); + return; + } } } } @@ -100,25 +100,31 @@ TEST_P(AvgPredTest, CompareReferenceRandom) { const int height = 32; Buffer ref = Buffer(width, height, 8); ASSERT_TRUE(ref.Init()); - DECLARE_ALIGNED(16, uint8_t, pred[width * height]); - DECLARE_ALIGNED(16, uint8_t, avg_ref[width * height]); - DECLARE_ALIGNED(16, uint8_t, avg_chk[width * height]); + Buffer pred = Buffer(width, height, 0, 16); + ASSERT_TRUE(pred.Init()); + Buffer avg_ref = Buffer(width, height, 0, 16); + ASSERT_TRUE(avg_ref.Init()); + Buffer avg_chk = Buffer(width, height, 0, 16); + ASSERT_TRUE(avg_chk.Init()); for (int i = 0; i < 500; ++i) { - fill(&rnd_, pred, width, height); ref.Set(&rnd_, &ACMRandom::Rand8); + pred.Set(&rnd_, &ACMRandom::Rand8); - reference_pred(pred, ref, width, height, avg_ref); - ASM_REGISTER_STATE_CHECK(avg_pred_func_(avg_chk, pred, width, height, + reference_pred(pred, ref, width, height, &avg_ref); + ASM_REGISTER_STATE_CHECK(avg_pred_func_(avg_chk.TopLeftPixel(), + pred.TopLeftPixel(), width, height, ref.TopLeftPixel(), ref.stride())); - ASSERT_EQ(memcmp(avg_ref, avg_chk, sizeof(*avg_ref) * width * height), 0); + EXPECT_TRUE(avg_chk.CheckValues(avg_ref)); + if (HasFailure()) { + printf("Width: %d Height: %d\n", width, height); + avg_chk.PrintDifference(avg_ref); + return; + } } } TEST_P(AvgPredTest, DISABLED_Speed) { - DECLARE_ALIGNED(16, uint8_t, pred[64 * 64]); - DECLARE_ALIGNED(16, uint8_t, avg[64 * 64]); - for (int width_pow = 2; width_pow <= 6; ++width_pow) { for (int height_pow = width_pow - 1; height_pow <= width_pow + 1; ++height_pow) { @@ -131,15 +137,19 @@ TEST_P(AvgPredTest, DISABLED_Speed) { Buffer ref = Buffer(width, height, ref_padding ? 8 : 0); ASSERT_TRUE(ref.Init()); + Buffer pred = Buffer(width, height, 0, 16); + ASSERT_TRUE(pred.Init()); + Buffer avg = Buffer(width, height, 0, 16); + ASSERT_TRUE(avg.Init()); - fill(&rnd_, pred, width, height); ref.Set(&rnd_, &ACMRandom::Rand8); + pred.Set(&rnd_, &ACMRandom::Rand8); vpx_usec_timer timer; vpx_usec_timer_start(&timer); for (int i = 0; i < 10000000 / (width * height); ++i) { - avg_pred_func_(avg, pred, width, height, ref.TopLeftPixel(), - ref.stride()); + avg_pred_func_(avg.TopLeftPixel(), pred.TopLeftPixel(), width, height, + ref.TopLeftPixel(), ref.stride()); } vpx_usec_timer_mark(&timer); -- 2.7.4