]> granicus.if.org Git - libvpx/commitdiff
VSX version of vpx_quantize_b_vsx
authorLuc Trudeau <luc@trud.ca>
Wed, 9 May 2018 03:00:20 +0000 (23:00 -0400)
committerJohann Koenig <johannkoenig@google.com>
Wed, 9 May 2018 17:54:27 +0000 (17:54 +0000)
Low bit depth version only. Passes the VP9QuantizeTest.

Change-Id: I6546f872864bd404a7e353348b0554aab1de5bf0

test/vp9_quantize_test.cc
vpx_dsp/ppc/quantize_vsx.c [new file with mode: 0644]
vpx_dsp/ppc/types_vsx.h
vpx_dsp/vpx_dsp.mk
vpx_dsp/vpx_dsp_rtcd_defs.pl

index 4740cadd9382373059aae74df8839bb95501b8a5..f0bbedbfa033541003f20849f2399e49f0ff22f0 100644 (file)
@@ -575,3 +575,10 @@ INSTANTIATE_TEST_CASE_P(
                    &QuantFPWrapper<vp9_quantize_fp_32x32_c>, VPX_BITS_8, 32,
                    true)));
 }  // namespace
+
+#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(VSX, VP9QuantizeTest,
+                        ::testing::Values(make_tuple(&vpx_quantize_b_vsx,
+                                                     &vpx_quantize_b_c,
+                                                     VPX_BITS_8, 16, false)));
+#endif  // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH
diff --git a/vpx_dsp/ppc/quantize_vsx.c b/vpx_dsp/ppc/quantize_vsx.c
new file mode 100644 (file)
index 0000000..e037f89
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (c) 2018 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+
+#include "./vpx_dsp_rtcd.h"
+#include "vpx_dsp/ppc/types_vsx.h"
+
+// Negate 16-bit integers in a when the corresponding signed 16-bit
+// integer in b is negative.
+static INLINE int16x8_t vec_sign(int16x8_t a, int16x8_t b) {
+  const int16x8_t mask = vec_sra(b, vec_shift_sign_s16);
+  return vec_xor(vec_add(a, mask), mask);
+}
+
+// Multiply the packed 16-bit integers in a and b, producing intermediate 32-bit
+// integers, and return the high 16 bits of the intermediate integers.
+static INLINE int16x8_t vec_mulhi(int16x8_t a, int16x8_t b) {
+  // madds does ((A * B) >>15) + C, we need >> 16, so we perform an extra right
+  // shift.
+  return vec_sra(vec_madds(a, b, vec_zeros_s16), vec_ones_s16);
+}
+
+static INLINE int16x8_t quantize_coeff(int16x8_t coeff, int16x8_t coeff_abs,
+                                       int16x8_t round, int16x8_t quant,
+                                       int16x8_t quant_shift, bool16x8_t mask) {
+  int16x8_t rounded, qcoeff;
+  rounded = vec_vaddshs(coeff_abs, round);
+  qcoeff = vec_mulhi(rounded, quant);
+  qcoeff = vec_add(qcoeff, rounded);
+  qcoeff = vec_mulhi(qcoeff, quant_shift);
+  qcoeff = vec_sign(qcoeff, coeff);
+  return vec_and(qcoeff, mask);
+}
+
+static INLINE int16x8_t nonzero_scanindex(int16x8_t qcoeff, bool16x8_t mask,
+                                          const int16_t *iscan_ptr) {
+  bool16x8_t zero_coeff;
+  int16x8_t scan = vec_vsx_ld(0, iscan_ptr);
+  zero_coeff = vec_cmpeq(qcoeff, vec_zeros_s16);
+  scan = vec_sub(scan, mask);
+  return vec_andc(scan, zero_coeff);
+}
+
+// Compare packed 16-bit integers across a, and return the maximum value in
+// every element. Returns a vector containing the biggest value across vector a.
+static INLINE int16x8_t vec_max_across(int16x8_t a) {
+  a = vec_max(a, vec_perm(a, a, vec_perm64));
+  a = vec_max(a, vec_perm(a, a, vec_perm32));
+  return vec_max(a, vec_perm(a, a, vec_perm16));
+}
+
+void vpx_quantize_b_vsx(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
+                        int skip_block, const int16_t *zbin_ptr,
+                        const int16_t *round_ptr, const int16_t *quant_ptr,
+                        const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
+                        tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
+                        uint16_t *eob_ptr, const int16_t *scan_ptr,
+                        const int16_t *iscan_ptr) {
+  int16x8_t qcoeff, dqcoeff, eob;
+
+  // First set of 8 coeff starts with DC + 7 AC
+  int16x8_t zbin = vec_vsx_ld(0, zbin_ptr);
+  int16x8_t round = vec_vsx_ld(0, round_ptr);
+  int16x8_t quant = vec_vsx_ld(0, quant_ptr);
+  int16x8_t dequant = vec_vsx_ld(0, dequant_ptr);
+  int16x8_t quant_shift = vec_vsx_ld(0, quant_shift_ptr);
+
+  int16x8_t coeff = vec_vsx_ld(0, coeff_ptr);
+  int16x8_t coeff_abs = vec_abs(coeff);
+  bool16x8_t zero_mask = vec_cmpge(coeff_abs, zbin);
+
+  (void)scan_ptr;
+  (void)skip_block;
+  assert(!skip_block);
+
+  qcoeff =
+      quantize_coeff(coeff, coeff_abs, round, quant, quant_shift, zero_mask);
+  vec_vsx_st(qcoeff, 0, qcoeff_ptr);
+
+  dqcoeff = vec_mladd(qcoeff, dequant, vec_zeros_s16);
+  vec_vsx_st(dqcoeff, 0, dqcoeff_ptr);
+
+  eob = nonzero_scanindex(qcoeff, zero_mask, iscan_ptr);
+
+  // All other sets of 8 coeffs will only contain AC
+  zbin = vec_splat(zbin, 1);
+  round = vec_splat(round, 1);
+  quant = vec_splat(quant, 1);
+  dequant = vec_splat(dequant, 1);
+  quant_shift = vec_splat(quant_shift, 1);
+
+  n_coeffs -= 8;
+  do {
+    coeff_ptr += 8;
+    qcoeff_ptr += 8;
+    dqcoeff_ptr += 8;
+    iscan_ptr += 8;
+
+    coeff = vec_vsx_ld(0, coeff_ptr);
+    coeff_abs = vec_abs(coeff);
+    zero_mask = vec_cmpge(coeff_abs, zbin);
+    qcoeff =
+        quantize_coeff(coeff, coeff_abs, round, quant, quant_shift, zero_mask);
+    vec_vsx_st(qcoeff, 0, qcoeff_ptr);
+
+    dqcoeff = vec_mladd(qcoeff, dequant, vec_zeros_s16);
+    vec_vsx_st(dqcoeff, 0, dqcoeff_ptr);
+
+    eob = vec_max(eob, nonzero_scanindex(qcoeff, zero_mask, iscan_ptr));
+
+    n_coeffs -= 8;
+  } while (n_coeffs > 0);
+
+  eob = vec_max_across(eob);
+  *eob_ptr = eob[0];
+}
index f611d02d2d580e49c0980236f122d26cc9120616..e2af55463ef43e208bca594eb2967a59279bfb7d 100644 (file)
@@ -19,6 +19,7 @@ typedef vector signed short int16x8_t;
 typedef vector unsigned short uint16x8_t;
 typedef vector signed int int32x4_t;
 typedef vector unsigned int uint32x4_t;
+typedef vector bool short bool16x8_t;
 
 #ifdef __clang__
 static const uint8x16_t xxpermdi0_perm = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
@@ -65,4 +66,17 @@ static const uint8x16_t xxpermdi3_perm = { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
 #endif
 #endif
 
+static const int16x8_t vec_zeros_s16 = { 0, 0, 0, 0, 0, 0, 0, 0 };
+static const uint16x8_t vec_ones_s16 = { 1, 1, 1, 1, 1, 1, 1, 1 };
+static const uint16x8_t vec_shift_sign_s16 = { 15, 15, 15, 15, 15, 15, 15, 15 };
+static const uint8x16_t vec_perm64 = { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+                                       0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03,
+                                       0x04, 0x05, 0x06, 0x07 };
+static const uint8x16_t vec_perm32 = { 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+                                       0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+                                       0x00, 0x01, 0x02, 0x03 };
+static const uint8x16_t vec_perm16 = { 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                                       0x08, 0x09, 0x0A, 0x0B, 0x0E, 0x0D,
+                                       0x0E, 0x0F, 0x00, 0x01 };
+
 #endif  // VPX_DSP_PPC_TYPES_VSX_H_
index 0cdb708494d67ec5bedfbf6612667f9c3dd6fec4..cb06a476f2aaa30c3966127d0be5b19aea87bd8b 100644 (file)
@@ -286,6 +286,7 @@ DSP_SRCS-$(HAVE_SSE2)   += x86/quantize_sse2.c
 DSP_SRCS-$(HAVE_SSSE3)  += x86/quantize_ssse3.c
 DSP_SRCS-$(HAVE_AVX)    += x86/quantize_avx.c
 DSP_SRCS-$(HAVE_NEON)   += arm/quantize_neon.c
+DSP_SRCS-$(HAVE_VSX)    += ppc/quantize_vsx.c
 ifeq ($(CONFIG_VP9_HIGHBITDEPTH),yes)
 DSP_SRCS-$(HAVE_SSE2)   += x86/highbd_quantize_intrin_sse2.c
 endif
index 8dfcb727690ca5c12a037b7451fe693a07f354b5..93ecd7c19aaac5fb4209a75120c5de8eddd7d691 100644 (file)
@@ -699,7 +699,7 @@ if (vpx_config("CONFIG_VP9_HIGHBITDEPTH") eq "yes") {
 #
 if (vpx_config("CONFIG_VP9_ENCODER") eq "yes") {
   add_proto qw/void vpx_quantize_b/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
-  specialize qw/vpx_quantize_b neon sse2 ssse3 avx/;
+  specialize qw/vpx_quantize_b neon sse2 ssse3 avx vsx/;
 
   add_proto qw/void vpx_quantize_b_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan";
   specialize qw/vpx_quantize_b_32x32 neon ssse3 avx/;