From e8af6cb2e4e6f2c3a1936cdee2e97f4e39f416f6 Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Sat, 1 Apr 2023 07:28:00 -0700 Subject: Add RAWToARGBRow_RVV,RAWToRGBARow_RVV,RAWToRGB24Row_RVV * Run on SiFive internal FPGA: RAWToARGB_Opt (~2x vs scalar) RAWToRGBA_Opt (~2x vs scalar) RAWToRGB24_Opt (~1.5x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Change-Id: I21a13d646589ea2aa3822cb9225f5191068c285b Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4408357 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 source/row_rvv.cc (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc new file mode 100644 index 00000000..0f264d34 --- /dev/null +++ b/source/row_rvv.cc @@ -0,0 +1,75 @@ +/* + * Copyright 2023 The LibYuv 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. + */ + +/* + * Copyright (c) 2023 SiFive, Inc. All rights reserved. + * + * Contributed by Darren Hsieh + * + */ + +#include + +#include "libyuv/row.h" + +#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) +#include + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { + size_t vl = __riscv_vsetvl_e8m2(width); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + while (width > 0) { + vuint8m2_t v_b, v_g, v_r; + vl = __riscv_vsetvl_e8m2(width); + __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + width -= vl; + src_raw += (3 * vl); + dst_argb += (4 * vl); + } +} + +void RAWToRGBARow_RVV(const uint8_t* src_raw, uint8_t* dst_rgba, int width) { + size_t vl = __riscv_vsetvl_e8m2(width); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + while (width > 0) { + vuint8m2_t v_b, v_g, v_r; + vl = __riscv_vsetvl_e8m2(width); + __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); + __riscv_vsseg4e8_v_u8m2(dst_rgba, v_a, v_b, v_g, v_r, vl); + width -= vl; + src_raw += (3 * vl); + dst_rgba += (4 * vl); + } +} + +void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { + while (width > 0) { + vuint8m2_t v_b, v_g, v_r; + size_t vl = __riscv_vsetvl_e8m2(width); + __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_raw, vl); + __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_r, v_g, v_b, vl); + width -= vl; + src_raw += (3 * vl); + dst_rgb24 += (3 * vl); + } +} + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif + +#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) -- cgit v1.2.3 From 44396e6e9aad554283c8f1fbe981ac122c40dfc7 Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Sun, 9 Apr 2023 21:34:25 -0700 Subject: Add ARGBToRAWRow_RVV, ARGBToRGB24Row_RVV, RGB24ToARGBRow_RVV * Run on SiFive internal FPGA: ARGBToRAW_Opt (~1.55x vs scalar) ARGBToRGB24_Opt (~1.44x vs scalar) RGB24ToARGB_Opt (~1.77x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Bug: libyuv:956 Change-Id: I26722f6848cd68684d95d9a7ee06ce0416e7985d Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4413083 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 58 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 8 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 0f264d34..629eca46 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -30,33 +30,33 @@ extern "C" { void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { size_t vl = __riscv_vsetvl_e8m2(width); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); - while (width > 0) { + do { vuint8m2_t v_b, v_g, v_r; - vl = __riscv_vsetvl_e8m2(width); __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); width -= vl; src_raw += (3 * vl); dst_argb += (4 * vl); - } + vl = __riscv_vsetvl_e8m2(width); + } while (width > 0); } void RAWToRGBARow_RVV(const uint8_t* src_raw, uint8_t* dst_rgba, int width) { size_t vl = __riscv_vsetvl_e8m2(width); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); - while (width > 0) { + do { vuint8m2_t v_b, v_g, v_r; - vl = __riscv_vsetvl_e8m2(width); __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); __riscv_vsseg4e8_v_u8m2(dst_rgba, v_a, v_b, v_g, v_r, vl); width -= vl; src_raw += (3 * vl); dst_rgba += (4 * vl); - } + vl = __riscv_vsetvl_e8m2(width); + } while (width > 0); } void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { - while (width > 0) { + do { vuint8m2_t v_b, v_g, v_r; size_t vl = __riscv_vsetvl_e8m2(width); __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_raw, vl); @@ -64,7 +64,49 @@ void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { width -= vl; src_raw += (3 * vl); dst_rgb24 += (3 * vl); - } + } while (width > 0); +} + +void ARGBToRAWRow_RVV(const uint8_t* src_argb, uint8_t* dst_raw, int width) { + do { + vuint8m2_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m2(width); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vsseg3e8_v_u8m2(dst_raw, v_r, v_g, v_b, vl); + width -= vl; + src_argb += (4 * vl); + dst_raw += (3 * vl); + } while (width > 0); +} + +void ARGBToRGB24Row_RVV(const uint8_t* src_argb, + uint8_t* dst_rgb24, + int width) { + do { + vuint8m2_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m2(width); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); + width -= vl; + src_argb += (4 * vl); + dst_rgb24 += (3 * vl); + } while (width > 0); +} + +void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, + uint8_t* dst_argb, + int width) { + size_t vl = __riscv_vsetvl_e8m2(width); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + do { + vuint8m2_t v_b, v_g, v_r; + __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_rgb24, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + width -= vl; + src_rgb24 += (3 * vl); + dst_argb += (4 * vl); + vl = __riscv_vsetvl_e8m2(width); + } while (width > 0); } #ifdef __cplusplus -- cgit v1.2.3 From 1330a79e9fcd86d06c26b5be861a6ff7946893f4 Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Sun, 9 Apr 2023 22:42:30 -0700 Subject: Optimized AR64/AB64 <-> ARGB with RVV * Run on SiFive internal FPGA: ARGBToAR64_Opt (~13.7x vs scalar) ARGBToAB64_Opt (~5.81x vs scalar) AR64ToARGB_Opt (~15.8x vs scalar) AB64ToARGB_Opt (~2.40x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Bug: libyuv:956 Change-Id: Ida642a5077f59d25fb7c5328f671956b2293dadd Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4442913 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 629eca46..bd21d44e 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -12,7 +12,7 @@ * Copyright (c) 2023 SiFive, Inc. All rights reserved. * * Contributed by Darren Hsieh - * + * Contributed by Bruce Lai */ #include @@ -27,6 +27,77 @@ namespace libyuv { extern "C" { #endif +void ARGBToAR64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ar64, int width) { + size_t avl = (size_t)4 * width; + do { + vuint16m8_t v_ar64; + vuint8m4_t v_argb; + size_t vl = __riscv_vsetvl_e8m4(avl); + v_argb = __riscv_vle8_v_u8m4(src_argb, vl); + v_ar64 = __riscv_vwaddu_vx_u16m8(v_argb, 0, vl); + v_ar64 = __riscv_vmul_vx_u16m8(v_ar64, 0x0101, vl); + __riscv_vse16_v_u16m8(dst_ar64, v_ar64, vl); + avl -= vl; + src_argb += vl; + dst_ar64 += vl; + } while (avl > 0); +} + +void ARGBToAB64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ab64, int width) { + size_t avl = (size_t)width; + do { + vuint16m2_t v_b_16, v_g_16, v_r_16, v_a_16; + vuint8m1_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m1(avl); + __riscv_vlseg4e8_v_u8m1(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + v_b_16 = __riscv_vwaddu_vx_u16m2(v_b, 0, vl); + v_g_16 = __riscv_vwaddu_vx_u16m2(v_g, 0, vl); + v_r_16 = __riscv_vwaddu_vx_u16m2(v_r, 0, vl); + v_a_16 = __riscv_vwaddu_vx_u16m2(v_a, 0, vl); + v_b_16 = __riscv_vmul_vx_u16m2(v_b_16, 0x0101, vl); + v_g_16 = __riscv_vmul_vx_u16m2(v_g_16, 0x0101, vl); + v_r_16 = __riscv_vmul_vx_u16m2(v_r_16, 0x0101, vl); + v_a_16 = __riscv_vmul_vx_u16m2(v_a_16, 0x0101, vl); + __riscv_vsseg4e16_v_u16m2(dst_ab64, v_r_16, v_g_16, v_b_16, v_a_16, vl); + avl -= vl; + src_argb += 4 * vl; + dst_ab64 += 4 * vl; + } while (avl > 0); +} + +void AR64ToARGBRow_RVV(const uint16_t* src_ar64, uint8_t* dst_argb, int width) { + size_t avl = (size_t)4 * width; + do { + vuint16m8_t v_ar64; + vuint8m4_t v_argb; + size_t vl = __riscv_vsetvl_e16m8(avl); + v_ar64 = __riscv_vle16_v_u16m8(src_ar64, vl); + v_argb = __riscv_vnsrl_wx_u8m4(v_ar64, 8, vl); + __riscv_vse8_v_u8m4(dst_argb, v_argb, vl); + avl -= vl; + src_ar64 += vl; + dst_argb += vl; + } while (avl > 0); +} + +void AB64ToARGBRow_RVV(const uint16_t* src_ab64, uint8_t* dst_argb, int width) { + size_t avl = (size_t)width; + do { + vuint16m2_t v_b_16, v_g_16, v_r_16, v_a_16; + vuint8m1_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e16m2(avl); + __riscv_vlseg4e16_v_u16m2(&v_r_16, &v_g_16, &v_b_16, &v_a_16, src_ab64, vl); + v_b = __riscv_vnsrl_wx_u8m1(v_b_16, 8, vl); + v_g = __riscv_vnsrl_wx_u8m1(v_g_16, 8, vl); + v_r = __riscv_vnsrl_wx_u8m1(v_r_16, 8, vl); + v_a = __riscv_vnsrl_wx_u8m1(v_a_16, 8, vl); + __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + avl -= vl; + src_ab64 += 4 * vl; + dst_argb += 4 * vl; + } while (avl > 0); +} + void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { size_t vl = __riscv_vsetvl_e8m2(width); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); -- cgit v1.2.3 From 1b3c4c12d4b7972b6656438a37949309bfb2c18a Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Tue, 11 Apr 2023 00:05:48 -0700 Subject: Add Split/Merge RGB/ARGB/XRGB Row_RVV * Run on SiFive internal FPGA: SplitRGBPlane_Opt (~6.87x vs scalar) SplitARGBPlane_Opt (~10.77x vs scalar) SplitXRGBPlane_Opt (~18.69x vs scalar) MergeRGBPlane_Opt (~3.63x vs scalar) MergeARGBPlane_Opt (~3.50x vs scalar) MergeXRGBPlane_Opt (~2.90x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 - include a fix to avoid implict conversion warning between size_t & int. Bug: libyuv:956 Change-Id: Icd79b282b04ea3981e7fd4e6d547da6708d82516 Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4443411 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 204 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 171 insertions(+), 33 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index bd21d44e..0ca4740b 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -99,85 +99,223 @@ void AB64ToARGBRow_RVV(const uint16_t* src_ab64, uint8_t* dst_argb, int width) { } void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { - size_t vl = __riscv_vsetvl_e8m2(width); + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { vuint8m2_t v_b, v_g, v_r; __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); - width -= vl; - src_raw += (3 * vl); - dst_argb += (4 * vl); - vl = __riscv_vsetvl_e8m2(width); - } while (width > 0); + w -= vl; + src_raw += vl * 3; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); } void RAWToRGBARow_RVV(const uint8_t* src_raw, uint8_t* dst_rgba, int width) { - size_t vl = __riscv_vsetvl_e8m2(width); + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { vuint8m2_t v_b, v_g, v_r; __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_raw, vl); __riscv_vsseg4e8_v_u8m2(dst_rgba, v_a, v_b, v_g, v_r, vl); - width -= vl; - src_raw += (3 * vl); - dst_rgba += (4 * vl); - vl = __riscv_vsetvl_e8m2(width); - } while (width > 0); + w -= vl; + src_raw += vl * 3; + dst_rgba += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); } void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { + size_t w = (size_t)width; do { vuint8m2_t v_b, v_g, v_r; - size_t vl = __riscv_vsetvl_e8m2(width); + size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_raw, vl); __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_r, v_g, v_b, vl); - width -= vl; - src_raw += (3 * vl); - dst_rgb24 += (3 * vl); - } while (width > 0); + w -= vl; + src_raw += vl * 3; + dst_rgb24 += vl * 3; + } while (w > 0); } void ARGBToRAWRow_RVV(const uint8_t* src_argb, uint8_t* dst_raw, int width) { + size_t w = (size_t)width; do { vuint8m2_t v_b, v_g, v_r, v_a; - size_t vl = __riscv_vsetvl_e8m2(width); + size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); __riscv_vsseg3e8_v_u8m2(dst_raw, v_r, v_g, v_b, vl); - width -= vl; - src_argb += (4 * vl); - dst_raw += (3 * vl); - } while (width > 0); + w -= vl; + src_argb += vl * 4; + dst_raw += vl * 3; + } while (w > 0); } void ARGBToRGB24Row_RVV(const uint8_t* src_argb, uint8_t* dst_rgb24, int width) { + size_t w = (size_t)width; do { vuint8m2_t v_b, v_g, v_r, v_a; - size_t vl = __riscv_vsetvl_e8m2(width); + size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); - width -= vl; - src_argb += (4 * vl); - dst_rgb24 += (3 * vl); - } while (width > 0); + w -= vl; + src_argb += vl * 4; + dst_rgb24 += vl * 3; + } while (w > 0); } void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_argb, int width) { - size_t vl = __riscv_vsetvl_e8m2(width); + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { vuint8m2_t v_b, v_g, v_r; __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_rgb24, vl); __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); - width -= vl; - src_rgb24 += (3 * vl); - dst_argb += (4 * vl); - vl = __riscv_vsetvl_e8m2(width); - } while (width > 0); + w -= vl; + src_rgb24 += vl * 3; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); +} + +void SplitRGBRow_RVV(const uint8_t* src_rgb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width) { + size_t w = (size_t)width; + do { + vuint8m2_t v_b, v_g, v_r; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg3e8_v_u8m2(&v_r, &v_g, &v_b, src_rgb, vl); + __riscv_vse8_v_u8m2(dst_r, v_r, vl); + __riscv_vse8_v_u8m2(dst_g, v_g, vl); + __riscv_vse8_v_u8m2(dst_b, v_b, vl); + w -= vl; + dst_r += vl; + dst_g += vl; + dst_b += vl; + src_rgb += vl * 3; + } while (w > 0); +} + +void MergeRGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_rgb, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_r = __riscv_vle8_v_u8m2(src_r, vl); + vuint8m2_t v_g = __riscv_vle8_v_u8m2(src_g, vl); + vuint8m2_t v_b = __riscv_vle8_v_u8m2(src_b, vl); + __riscv_vsseg3e8_v_u8m2(dst_rgb, v_r, v_g, v_b, vl); + w -= vl; + src_r += vl; + src_g += vl; + src_b += vl; + dst_rgb += vl * 3; + } while (w > 0); +} + +void SplitARGBRow_RVV(const uint8_t* src_argb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + uint8_t* dst_a, + int width) { + size_t w = (size_t)width; + do { + vuint8m2_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vse8_v_u8m2(dst_a, v_a, vl); + __riscv_vse8_v_u8m2(dst_r, v_r, vl); + __riscv_vse8_v_u8m2(dst_g, v_g, vl); + __riscv_vse8_v_u8m2(dst_b, v_b, vl); + w -= vl; + dst_a += vl; + dst_r += vl; + dst_g += vl; + dst_b += vl; + src_argb += vl * 4; + } while (w > 0); +} + +void MergeARGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + const uint8_t* src_a, + uint8_t* dst_argb, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_r = __riscv_vle8_v_u8m2(src_r, vl); + vuint8m2_t v_g = __riscv_vle8_v_u8m2(src_g, vl); + vuint8m2_t v_b = __riscv_vle8_v_u8m2(src_b, vl); + vuint8m2_t v_a = __riscv_vle8_v_u8m2(src_a, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_r += vl; + src_g += vl; + src_b += vl; + src_a += vl; + dst_argb += vl * 4; + } while (w > 0); +} + +void SplitXRGBRow_RVV(const uint8_t* src_argb, + uint8_t* dst_r, + uint8_t* dst_g, + uint8_t* dst_b, + int width) { + size_t w = (size_t)width; + do { + vuint8m2_t v_b, v_g, v_r, v_a; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vse8_v_u8m2(dst_r, v_r, vl); + __riscv_vse8_v_u8m2(dst_g, v_g, vl); + __riscv_vse8_v_u8m2(dst_b, v_b, vl); + w -= vl; + dst_r += vl; + dst_g += vl; + dst_b += vl; + src_argb += vl * 4; + } while (w > 0); +} + +void MergeXRGBRow_RVV(const uint8_t* src_r, + const uint8_t* src_g, + const uint8_t* src_b, + uint8_t* dst_argb, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + do { + vuint8m2_t v_r, v_g, v_b; + v_r = __riscv_vle8_v_u8m2(src_r, vl); + v_g = __riscv_vle8_v_u8m2(src_g, vl); + v_b = __riscv_vle8_v_u8m2(src_b, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_r += vl; + src_g += vl; + src_b += vl; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); } #ifdef __cplusplus -- cgit v1.2.3 From f4bd840794ec09fc1e493398a032f6026fb01ea3 Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Thu, 27 Apr 2023 18:53:01 -0700 Subject: Fix compile error for riscv scalar & simplify cmake cross build flow 1. Fix compile error when build riscv without using vector 2. Fix run_qemu.sh misused v=true for USE_RVV=OFF case 3. [cmake] Fix warning by rename TEST to UNIT_TEST Warning log: CMake Warning (dev) at CMakeLists.txt:57 (if): [54/1931] Policy CMP0064 is not set: Support new TEST if() operator. Run "cmake --help-policy CMP0064" for policy details. Use the cmake_policy command to set the policy and suppress this warning. TEST will be interpreted as an operator when the policy is set to NEW. Since the policy is not set the OLD behavior will be used. This warning is for project developers. Use -Wno-dev to suppress it. 4. [cmake] Simplify logic for cross-build Bug: libyuv:956 Change-Id: I120402fc7d6d86403e7d974180b81f4f9c663e36 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4486239 Reviewed-by: Frank Barchard Reviewed-by: Mirko Bonadei Commit-Queue: Frank Barchard --- source/row_rvv.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 0ca4740b..956ed9f9 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -19,7 +19,7 @@ #include "libyuv/row.h" -#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) +#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) #include #ifdef __cplusplus @@ -323,4 +323,4 @@ void MergeXRGBRow_RVV(const uint8_t* src_r, } // namespace libyuv #endif -#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv) +#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) -- cgit v1.2.3 From 964d963afb164e768919f5bd2284202d87a3d37c Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Tue, 2 May 2023 00:33:27 -0700 Subject: Enable I422To{ARGB,RGBA,RGB24}Row_RVV Run on SiFive internal FPGA: I422ToARGB_Opt (~10x vs scalar) I422ToRGBA_Opt (~10x vs scalar) I420ToRGB24_Opt (~8x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 This CL manually sets rounding mode, since we use fixed-point vector narrowing clip. There is no definition about default value for fixed-point rounding mode. https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#38-vector-fixed-point-rounding-mode-register-vxrm The behavior could be different on differet paltforms. To avoid unexpected behavior, we set rounding mode manually. Change-Id: I90f0dcb90c37f7da7caab8eb1df6c9c7a3c874a8 Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4512373 Reviewed-by: Wan-Teh Chang Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 956ed9f9..475d3e66 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -27,6 +27,72 @@ namespace libyuv { extern "C" { #endif +// Fill YUV -> RGB conversion constants into vectors +// NOTE: To match behavior on other platforms, vxrm (fixed-point rounding mode +// register) is set to round-down mode(2). +#define YUVTORGB_SETUP(yuvconst, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, \ + v_br) \ + { \ + asm volatile("csrwi vxrm, 2"); \ + vl = __riscv_vsetvl_e8m1(w); \ + v_ub = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[0], vl); \ + v_vr = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[1], vl); \ + v_ug = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[2], vl); \ + v_vg = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[3], vl); \ + v_yg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[0], vl); \ + v_bb = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[1], vl); \ + v_bg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[2], vl); \ + v_br = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[3], vl); \ + } + +// Read [VLEN/8] Y, [VLEN/(8 * 2)] U and [VLEN/(8 * 2)] V from 422 +#define READYUV422(vl, v_u, v_v, v_y_16) \ + { \ + vuint8mf2_t v_tmp0, v_tmp1; \ + vuint8m1_t v_y; \ + vuint16m1_t v_u_16, v_v_16; \ + vl = __riscv_vsetvl_e8mf2((w + 1) / 2); \ + v_tmp0 = __riscv_vle8_v_u8mf2(src_u, vl); \ + v_u_16 = __riscv_vwaddu_vx_u16m1(v_tmp0, 0, vl); \ + v_tmp1 = __riscv_vle8_v_u8mf2(src_v, vl); \ + v_v_16 = __riscv_vwaddu_vx_u16m1(v_tmp1, 0, vl); \ + v_v_16 = __riscv_vmul_vx_u16m1(v_v_16, 0x0101, vl); \ + v_u_16 = __riscv_vmul_vx_u16m1(v_u_16, 0x0101, vl); \ + v_v = __riscv_vreinterpret_v_u16m1_u8m1(v_v_16); \ + v_u = __riscv_vreinterpret_v_u16m1_u8m1(v_u_16); \ + vl = __riscv_vsetvl_e8m1(w); \ + v_y = __riscv_vle8_v_u8m1(src_y, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m2(v_y, 0, vl); \ + } + +// Convert from YUV to fixed point RGB +#define YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, \ + v_g_16, v_b_16, v_r_16) \ + { \ + vuint16m2_t v_tmp0, v_tmp1, v_tmp2, v_tmp3, v_tmp4; \ + vuint32m4_t v_tmp5; \ + v_tmp0 = __riscv_vwmulu_vv_u16m2(v_u, v_ug, vl); \ + v_y_16 = __riscv_vmul_vx_u16m2(v_y_16, 0x0101, vl); \ + v_tmp0 = __riscv_vwmaccu_vv_u16m2(v_tmp0, v_vg, v_v, vl); \ + v_tmp1 = __riscv_vwmulu_vv_u16m2(v_u, v_ub, vl); \ + v_tmp5 = __riscv_vwmulu_vv_u32m4(v_y_16, v_yg, vl); \ + v_tmp2 = __riscv_vnsrl_wx_u16m2(v_tmp5, 16, vl); \ + v_tmp3 = __riscv_vadd_vv_u16m2(v_tmp2, v_bg, vl); \ + v_tmp4 = __riscv_vadd_vv_u16m2(v_tmp2, v_tmp1, vl); \ + v_tmp2 = __riscv_vwmaccu_vv_u16m2(v_tmp2, v_vr, v_v, vl); \ + v_g_16 = __riscv_vssubu_vv_u16m2(v_tmp3, v_tmp0, vl); \ + v_b_16 = __riscv_vssubu_vv_u16m2(v_tmp4, v_bb, vl); \ + v_r_16 = __riscv_vssubu_vv_u16m2(v_tmp2, v_br, vl); \ + } + +// Convert from fixed point RGB To 8 bit RGB +#define RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r) \ + { \ + v_g = __riscv_vnclipu_wx_u8m1(v_g_16, 6, vl); \ + v_b = __riscv_vnclipu_wx_u8m1(v_b_16, 6, vl); \ + v_r = __riscv_vnclipu_wx_u8m1(v_r_16, 6, vl); \ + } + void ARGBToAR64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ar64, int width) { size_t avl = (size_t)4 * width; do { @@ -186,6 +252,95 @@ void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, } while (w > 0); } +void I422ToARGBRow_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r, v_a; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + v_a = __riscv_vmv_v_x_u8m1(255u, vl); + do { + READYUV422(vl, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_y += vl; + src_u += vl / 2; + src_v += vl / 2; + dst_argb += vl * 4; + } while (w > 0); +} + +void I422ToRGBARow_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgba, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r, v_a; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + v_a = __riscv_vmv_v_x_u8m1(255u, vl); + do { + READYUV422(vl, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m1(dst_rgba, v_a, v_b, v_g, v_r, vl); + w -= vl; + src_y += vl; + src_u += vl / 2; + src_v += vl / 2; + dst_rgba += vl * 4; + } while (w > 0); +} + +void I422ToRGB24Row_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + do { + READYUV422(vl, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg3e8_v_u8m1(dst_rgb24, v_b, v_g, v_r, vl); + w -= vl; + src_y += vl; + src_u += vl / 2; + src_v += vl / 2; + dst_rgb24 += vl * 3; + } while (w > 0); +} + void SplitRGBRow_RVV(const uint8_t* src_rgb, uint8_t* dst_r, uint8_t* dst_g, -- cgit v1.2.3 From 497ea35688f997edb4c42ef1cdd9f2ab4efb9e29 Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Tue, 9 May 2023 01:39:06 -0700 Subject: Enable I444To{ARGB,RGB24}Row_RVV Run on SiFive internal FPGA: I444ToARGB_Opt (~16x vs scalar) I444ToRGB24_Opt (~10x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Change-Id: Idae7dc46ef648beaa14b58ba3eb56b67b17c9b3b Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4520761 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 116 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 23 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 475d3e66..39ce71e4 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -65,24 +65,35 @@ extern "C" { v_y_16 = __riscv_vwaddu_vx_u16m2(v_y, 0, vl); \ } +// Read [VLEN/8] Y, [VLEN/8] U, and [VLEN/8] V from 444 +#define READYUV444(vl, v_u, v_v, v_y_16) \ + { \ + vuint8m1_t v_y; \ + vl = __riscv_vsetvl_e8m1(w); \ + v_y = __riscv_vle8_v_u8m1(src_y, vl); \ + v_u = __riscv_vle8_v_u8m1(src_u, vl); \ + v_v = __riscv_vle8_v_u8m1(src_v, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m2(v_y, 0, vl); \ + } + // Convert from YUV to fixed point RGB -#define YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, \ - v_g_16, v_b_16, v_r_16) \ - { \ - vuint16m2_t v_tmp0, v_tmp1, v_tmp2, v_tmp3, v_tmp4; \ - vuint32m4_t v_tmp5; \ - v_tmp0 = __riscv_vwmulu_vv_u16m2(v_u, v_ug, vl); \ - v_y_16 = __riscv_vmul_vx_u16m2(v_y_16, 0x0101, vl); \ - v_tmp0 = __riscv_vwmaccu_vv_u16m2(v_tmp0, v_vg, v_v, vl); \ - v_tmp1 = __riscv_vwmulu_vv_u16m2(v_u, v_ub, vl); \ - v_tmp5 = __riscv_vwmulu_vv_u32m4(v_y_16, v_yg, vl); \ - v_tmp2 = __riscv_vnsrl_wx_u16m2(v_tmp5, 16, vl); \ - v_tmp3 = __riscv_vadd_vv_u16m2(v_tmp2, v_bg, vl); \ - v_tmp4 = __riscv_vadd_vv_u16m2(v_tmp2, v_tmp1, vl); \ - v_tmp2 = __riscv_vwmaccu_vv_u16m2(v_tmp2, v_vr, v_v, vl); \ - v_g_16 = __riscv_vssubu_vv_u16m2(v_tmp3, v_tmp0, vl); \ - v_b_16 = __riscv_vssubu_vv_u16m2(v_tmp4, v_bb, vl); \ - v_r_16 = __riscv_vssubu_vv_u16m2(v_tmp2, v_br, vl); \ +#define YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, \ + v_y_16, v_g_16, v_b_16, v_r_16) \ + { \ + vuint16m2_t v_tmp0, v_tmp1, v_tmp2, v_tmp3, v_tmp4; \ + vuint32m4_t v_tmp5; \ + v_tmp0 = __riscv_vwmulu_vv_u16m2(v_u, v_ug, vl); \ + v_y_16 = __riscv_vmul_vx_u16m2(v_y_16, 0x0101, vl); \ + v_tmp0 = __riscv_vwmaccu_vv_u16m2(v_tmp0, v_vg, v_v, vl); \ + v_tmp1 = __riscv_vwmulu_vv_u16m2(v_u, v_ub, vl); \ + v_tmp5 = __riscv_vwmulu_vv_u32m4(v_y_16, v_yg, vl); \ + v_tmp2 = __riscv_vnsrl_wx_u16m2(v_tmp5, 16, vl); \ + v_tmp3 = __riscv_vadd_vv_u16m2(v_tmp2, v_bg, vl); \ + v_tmp4 = __riscv_vadd_vv_u16m2(v_tmp2, v_tmp1, vl); \ + v_tmp2 = __riscv_vwmaccu_vv_u16m2(v_tmp2, v_vr, v_v, vl); \ + v_g_16 = __riscv_vssubu_vv_u16m2(v_tmp3, v_tmp0, vl); \ + v_b_16 = __riscv_vssubu_vv_u16m2(v_tmp4, v_bb, vl); \ + v_r_16 = __riscv_vssubu_vv_u16m2(v_tmp2, v_br, vl); \ } // Convert from fixed point RGB To 8 bit RGB @@ -252,6 +263,65 @@ void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, } while (w > 0); } +void I444ToARGBRow_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r, v_a; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + v_a = __riscv_vmv_v_x_u8m1(255u, vl); + do { + READYUV444(vl, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_y += vl; + src_u += vl; + src_v += vl; + dst_argb += vl * 4; + } while (w > 0); +} + +void I444ToRGB24Row_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + do { + READYUV444(vl, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg3e8_v_u8m1(dst_rgb24, v_b, v_g, v_r, vl); + w -= vl; + src_y += vl; + src_u += vl; + src_v += vl; + dst_rgb24 += vl * 3; + } while (w > 0); +} + void I422ToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -270,8 +340,8 @@ void I422ToARGBRow_RVV(const uint8_t* src_y, v_a = __riscv_vmv_v_x_u8m1(255u, vl); do { READYUV422(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, v_g_16, - v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); w -= vl; @@ -300,8 +370,8 @@ void I422ToRGBARow_RVV(const uint8_t* src_y, v_a = __riscv_vmv_v_x_u8m1(255u, vl); do { READYUV422(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, v_g_16, - v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); __riscv_vsseg4e8_v_u8m1(dst_rgba, v_a, v_b, v_g, v_r, vl); w -= vl; @@ -329,8 +399,8 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, v_br); do { READYUV422(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, v_y_16, v_g_16, - v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); __riscv_vsseg3e8_v_u8m1(dst_rgb24, v_b, v_g, v_r, vl); w -= vl; -- cgit v1.2.3 From 59eae49f17c345aa4949271dea2bb088130793af Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Tue, 25 Apr 2023 02:08:45 -0700 Subject: Enable ARGBToYMatrixRow_RVV/RGBAToYMatrixRow_RVV/RGBToYMatrixRow_RVV Run on SiFive internal FPGA: ARGBToJ400_Opt (~6x vs scalar) RGBAToJ400_Opt (~6x vs scalar) RGB24ToJ400_Opt (~5.5x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Change-Id: Ia3ce8cea7962fbd8618cc23e850a7913c9cabf4f Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4521783 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 39ce71e4..99f23165 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -543,6 +543,173 @@ void MergeXRGBRow_RVV(const uint8_t* src_r, } while (w > 0); } +struct RgbConstants { + uint8_t kRGBToY[4]; + uint16_t kAddY; + uint16_t pad; +}; + +// RGB to JPeg coefficients +// B * 0.1140 coefficient = 29 +// G * 0.5870 coefficient = 150 +// R * 0.2990 coefficient = 77 +// Add 0.5 = 0x80 +static const struct RgbConstants kRgb24JPEGConstants = {{29, 150, 77, 0}, + 128, + 0}; + +static const struct RgbConstants kRawJPEGConstants = {{77, 150, 29, 0}, 128, 0}; + +// RGB to BT.601 coefficients +// B * 0.1016 coefficient = 25 +// G * 0.5078 coefficient = 129 +// R * 0.2578 coefficient = 66 +// Add 16.5 = 0x1080 + +static const struct RgbConstants kRgb24I601Constants = {{25, 129, 66, 0}, + 0x1080, + 0}; + +static const struct RgbConstants kRawI601Constants = {{66, 129, 25, 0}, + 0x1080, + 0}; + +// ARGB expects first 3 values to contain RGB and 4th value is ignored. +void ARGBToYMatrixRow_RVV(const uint8_t* src_argb, + uint8_t* dst_y, + int width, + const struct RgbConstants* rgbconstants) { + assert(width != 0); + size_t w = (size_t)width; + vuint8m2_t v_by, v_gy, v_ry; // vectors are to store RGBToY constant + vuint16m4_t v_addy; // vector is to store kAddY + size_t vl = __riscv_vsetvl_e8m2(w); + v_by = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[0], vl); + v_gy = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[1], vl); + v_ry = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[2], vl); + v_addy = __riscv_vmv_v_x_u16m4(rgbconstants->kAddY, vl); + do { + vuint8m2_t v_b, v_g, v_r, v_a, v_y; + vuint16m4_t v_y_u16; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + v_y_u16 = __riscv_vwmulu_vv_u16m4(v_r, v_ry, vl); + v_y_u16 = __riscv_vwmaccu_vv_u16m4(v_y_u16, v_gy, v_g, vl); + v_y_u16 = __riscv_vwmaccu_vv_u16m4(v_y_u16, v_by, v_b, vl); + v_y_u16 = __riscv_vadd_vv_u16m4(v_y_u16, v_addy, vl); + v_y = __riscv_vnsrl_wx_u8m2(v_y_u16, 8, vl); + __riscv_vse8_v_u8m2(dst_y, v_y, vl); + w -= vl; + src_argb += 4 * vl; + dst_y += vl; + } while (w > 0); +} + +void ARGBToYRow_RVV(const uint8_t* src_argb, uint8_t* dst_y, int width) { + ARGBToYMatrixRow_RVV(src_argb, dst_y, width, &kRgb24I601Constants); +} + +void ARGBToYJRow_RVV(const uint8_t* src_argb, uint8_t* dst_yj, int width) { + ARGBToYMatrixRow_RVV(src_argb, dst_yj, width, &kRgb24JPEGConstants); +} + +void ABGRToYRow_RVV(const uint8_t* src_abgr, uint8_t* dst_y, int width) { + ARGBToYMatrixRow_RVV(src_abgr, dst_y, width, &kRawI601Constants); +} + +void ABGRToYJRow_RVV(const uint8_t* src_abgr, uint8_t* dst_yj, int width) { + ARGBToYMatrixRow_RVV(src_abgr, dst_yj, width, &kRawJPEGConstants); +} + +// RGBA expects first value to be A and ignored, then 3 values to contain RGB. +void RGBAToYMatrixRow_RVV(const uint8_t* src_rgba, + uint8_t* dst_y, + int width, + const struct RgbConstants* rgbconstants) { + assert(width != 0); + size_t w = (size_t)width; + vuint8m2_t v_by, v_gy, v_ry; // vectors are to store RGBToY constant + vuint16m4_t v_addy; // vector is to store kAddY + size_t vl = __riscv_vsetvl_e8m2(w); + v_by = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[0], vl); + v_gy = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[1], vl); + v_ry = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[2], vl); + v_addy = __riscv_vmv_v_x_u16m4(rgbconstants->kAddY, vl); + do { + vuint8m2_t v_b, v_g, v_r, v_a, v_y; + vuint16m4_t v_y_u16; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_a, &v_b, &v_g, &v_r, src_rgba, vl); + v_y_u16 = __riscv_vwmulu_vv_u16m4(v_r, v_ry, vl); + v_y_u16 = __riscv_vwmaccu_vv_u16m4(v_y_u16, v_gy, v_g, vl); + v_y_u16 = __riscv_vwmaccu_vv_u16m4(v_y_u16, v_by, v_b, vl); + v_y_u16 = __riscv_vadd_vv_u16m4(v_y_u16, v_addy, vl); + v_y = __riscv_vnsrl_wx_u8m2(v_y_u16, 8, vl); + __riscv_vse8_v_u8m2(dst_y, v_y, vl); + w -= vl; + src_rgba += 4 * vl; + dst_y += vl; + } while (w > 0); +} + +void RGBAToYRow_RVV(const uint8_t* src_rgba, uint8_t* dst_y, int width) { + RGBAToYMatrixRow_RVV(src_rgba, dst_y, width, &kRgb24I601Constants); +} + +void RGBAToYJRow_RVV(const uint8_t* src_rgba, uint8_t* dst_yj, int width) { + RGBAToYMatrixRow_RVV(src_rgba, dst_yj, width, &kRgb24JPEGConstants); +} + +void BGRAToYRow_RVV(const uint8_t* src_bgra, uint8_t* dst_y, int width) { + RGBAToYMatrixRow_RVV(src_bgra, dst_y, width, &kRawI601Constants); +} + +void RGBToYMatrixRow_RVV(const uint8_t* src_rgb, + uint8_t* dst_y, + int width, + const struct RgbConstants* rgbconstants) { + assert(width != 0); + size_t w = (size_t)width; + vuint8m2_t v_by, v_gy, v_ry; // vectors are to store RGBToY constant + vuint16m4_t v_addy; // vector is to store kAddY + size_t vl = __riscv_vsetvl_e8m2(w); + v_by = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[0], vl); + v_gy = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[1], vl); + v_ry = __riscv_vmv_v_x_u8m2(rgbconstants->kRGBToY[2], vl); + v_addy = __riscv_vmv_v_x_u16m4(rgbconstants->kAddY, vl); + do { + vuint8m2_t v_b, v_g, v_r, v_y; + vuint16m4_t v_y_u16; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg3e8_v_u8m2(&v_b, &v_g, &v_r, src_rgb, vl); + v_y_u16 = __riscv_vwmulu_vv_u16m4(v_r, v_ry, vl); + v_y_u16 = __riscv_vwmaccu_vv_u16m4(v_y_u16, v_gy, v_g, vl); + v_y_u16 = __riscv_vwmaccu_vv_u16m4(v_y_u16, v_by, v_b, vl); + v_y_u16 = __riscv_vadd_vv_u16m4(v_y_u16, v_addy, vl); + v_y = __riscv_vnsrl_wx_u8m2(v_y_u16, 8, vl); + __riscv_vse8_v_u8m2(dst_y, v_y, vl); + w -= vl; + src_rgb += 3 * vl; + dst_y += vl; + } while (w > 0); +} + +void RGB24ToYJRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) { + RGBToYMatrixRow_RVV(src_rgb24, dst_yj, width, &kRgb24JPEGConstants); +} + +void RAWToYJRow_RVV(const uint8_t* src_raw, uint8_t* dst_yj, int width) { + RGBToYMatrixRow_RVV(src_raw, dst_yj, width, &kRawJPEGConstants); +} + +void RGB24ToYRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_y, int width) { + RGBToYMatrixRow_RVV(src_rgb24, dst_y, width, &kRgb24I601Constants); +} + +void RAWToYRow_RVV(const uint8_t* src_raw, uint8_t* dst_y, int width) { + RGBToYMatrixRow_RVV(src_raw, dst_y, width, &kRawI601Constants); +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv -- cgit v1.2.3 From 11d4536002b4748ff3ed795ce893335bbb5f79fe Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Wed, 10 May 2023 18:51:49 -0700 Subject: Enable I{422,444}AlphaToARGBRow_RVV & ARGBAttentuateRow_RVV Run on SiFive internal FPGA: I444AlphaToARGB_Opt (~16x vs scalar) I422AlphaToARGB_Opt (~10x vs scalar) ARGBAttenuate_Opt (~3x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Change-Id: I0046eb7af8104bc8e13cee1cb91a19f90940d5b0 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4535657 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 99f23165..ad131924 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -16,7 +16,6 @@ */ #include - #include "libyuv/row.h" #if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) @@ -293,6 +292,38 @@ void I444ToARGBRow_RVV(const uint8_t* src_y, } while (w > 0); } +void I444AlphaToARGBRow_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + const uint8_t* src_a, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r, v_a; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + do { + READYUV444(vl, v_u, v_v, v_y_16); + v_a = __riscv_vle8_v_u8m1(src_a, vl); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_y += vl; + src_a += vl; + src_u += vl; + src_v += vl; + dst_argb += vl * 4; + } while (w > 0); +} + void I444ToRGB24Row_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -352,6 +383,38 @@ void I422ToARGBRow_RVV(const uint8_t* src_y, } while (w > 0); } +void I422AlphaToARGBRow_RVV(const uint8_t* src_y, + const uint8_t* src_u, + const uint8_t* src_v, + const uint8_t* src_a, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t vl; + size_t w = (size_t)width; + vuint8m1_t v_u, v_v; + vuint8m1_t v_ub, v_vr, v_ug, v_vg; + vuint8m1_t v_b, v_g, v_r, v_a; + vuint16m2_t v_yg, v_bb, v_bg, v_br; + vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, + v_br); + do { + READYUV422(vl, v_u, v_v, v_y_16); + v_a = __riscv_vle8_v_u8m1(src_a, vl); + YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, + v_y_16, v_g_16, v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_y += vl; + src_a += vl; + src_u += vl / 2; + src_v += vl / 2; + dst_argb += vl * 4; + } while (w > 0); +} + void I422ToRGBARow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -710,6 +773,31 @@ void RAWToYRow_RVV(const uint8_t* src_raw, uint8_t* dst_y, int width) { RGBToYMatrixRow_RVV(src_raw, dst_y, width, &kRawI601Constants); } +void ARGBAttenuateRow_RVV(const uint8_t* src_argb, + uint8_t* dst_argb, + int width) { + size_t w = (size_t)width; + // To match behavior on other platforms, vxrm (fixed-point rounding mode + // register) is set to round-to-nearest-up(0). + asm volatile("csrwi vxrm, 0"); + do { + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_ba_16, v_ga_16, v_ra_16; + size_t vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + v_ba_16 = __riscv_vwmulu_vv_u16m4(v_b, v_a, vl); + v_ga_16 = __riscv_vwmulu_vv_u16m4(v_g, v_a, vl); + v_ra_16 = __riscv_vwmulu_vv_u16m4(v_r, v_a, vl); + v_b = __riscv_vnclipu_wx_u8m2(v_ba_16, 8, vl); + v_g = __riscv_vnclipu_wx_u8m2(v_ga_16, 8, vl); + v_r = __riscv_vnclipu_wx_u8m2(v_ra_16, 8, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_argb += vl * 4; + dst_argb += vl * 4; + } while (w > 0); +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv -- cgit v1.2.3 From a37799344d29dc8e4d3fb00ced5f07e5ce8bf1b9 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Tue, 16 May 2023 16:42:55 -0700 Subject: ARGBToI420Alpha function to convert ARGB to I420 with Alpha Bug: b/281866362 Change-Id: Ic1093a887fb483f134c78909cf1ee7495e7345ba Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4534100 Commit-Queue: Frank Barchard Reviewed-by: Wan-Teh Chang --- source/row_rvv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index ad131924..904cbf7d 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -15,10 +15,10 @@ * Contributed by Bruce Lai */ -#include #include "libyuv/row.h" #if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) +#include #include #ifdef __cplusplus -- cgit v1.2.3 From 179b0203e5bd9eeff84de30e03b2517fd3bcb654 Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang Date: Sat, 20 May 2023 16:09:43 -0700 Subject: Enable {J400/I400}ToARGBRow_RVV Run on SiFive internal FPGA*: I400ToARGB_Opt (~8x vs scalar) J400ToARGB_Opt (~10x vs scalar) LIBYUV_WIDTH=1280 LIBYUV_HEIGHT=720 LIBYUV_REPEAT=10 Bug: libyuv:956, libyuv:961 Change-Id: If4e21ec85c4ff79083ec16a6faae0e457129a8de Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4544972 Reviewed-by: Frank Barchard Commit-Queue: Wan-Teh Chang --- source/row_rvv.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 904cbf7d..89333321 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -474,6 +474,62 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, } while (w > 0); } +void I400ToARGBRow_RVV(const uint8_t* src_y, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + const bool is_yb_positive = (yuvconstants->kRGBCoeffBias[4] >= 0); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + vuint16m4_t v_yb; + vuint16m4_t v_yg = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[0], vl); + // To match behavior on other platforms, vxrm (fixed-point rounding mode + // register) sets to round-down mode(2). + asm volatile("csrwi vxrm, 2"); + if (is_yb_positive) { + v_yb = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[4], vl); + } else { + v_yb = __riscv_vmv_v_x_u16m4(-yuvconstants->kRGBCoeffBias[4], vl); + } + do { + vuint8m2_t v_y, v_out; + vuint16m4_t v_y_16, v_tmp0, v_tmp1, v_tmp2; + vuint32m8_t v_y1; + vl = __riscv_vsetvl_e8m2(w); + v_y = __riscv_vle8_v_u8m2(src_y, vl); + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); + v_tmp0 = __riscv_vmul_vx_u16m4(v_y_16, 0x0101, vl); // 257 * v_y + v_y1 = __riscv_vwmulu_vv_u32m8(v_tmp0, v_yg, vl); + v_tmp1 = __riscv_vnsrl_wx_u16m4(v_y1, 16, vl); + if (is_yb_positive) { + v_tmp2 = __riscv_vsaddu_vv_u16m4(v_tmp1, v_yb, vl); + } else { + v_tmp2 = __riscv_vssubu_vv_u16m4(v_tmp1, v_yb, vl); + } + v_out = __riscv_vnclipu_wx_u8m2(v_tmp2, 6, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_out, v_out, v_out, v_a, vl); + w -= vl; + src_y += vl; + dst_argb += vl * 4; + } while (w > 0); +} + +void J400ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a = __riscv_vmv_v_x_u8m2(255u, vl); + do { + vuint8m2_t v_y; + v_y = __riscv_vle8_v_u8m2(src_y, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_y, v_y, v_y, v_a, vl); + w -= vl; + src_y += vl; + dst_argb += vl * 4; + vl = __riscv_vsetvl_e8m2(w); + } while (w > 0); +} + void SplitRGBRow_RVV(const uint8_t* src_rgb, uint8_t* dst_r, uint8_t* dst_g, -- cgit v1.2.3 From de3e7fd14728d923d0bdc8e3aca06c8a61f014ce Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Sun, 21 May 2023 18:32:29 -0700 Subject: Manually remove rounding value inside yb(yuvconstant) in row_rvv.cc After libyuv:961 is completed, yb(yuvconstant) will no longer contain rounding bias +32 for fixed-point. This CL removes rounding bias(-32) manmually in row_rvv.cc. Hence, all fixed-point related codes' rounding mode is changed to round-to-nearest-up "0" in row_rvv.cc. Also, replace vwmul+vnsrl w/ vmulh in I400ToARGBRow_RVV. Bug: libyuv:956, libyuv:961 Change-Id: I10e34668a2332e38393e9d68414f07aafb6c7cf7 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4550591 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 89333321..be4c4a30 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -28,20 +28,20 @@ extern "C" { // Fill YUV -> RGB conversion constants into vectors // NOTE: To match behavior on other platforms, vxrm (fixed-point rounding mode -// register) is set to round-down mode(2). +// register) is set to round-to-nearest-up mode(0). #define YUVTORGB_SETUP(yuvconst, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, \ v_br) \ { \ - asm volatile("csrwi vxrm, 2"); \ + asm volatile("csrwi vxrm, 0"); \ vl = __riscv_vsetvl_e8m1(w); \ v_ub = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[0], vl); \ v_vr = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[1], vl); \ v_ug = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[2], vl); \ v_vg = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[3], vl); \ v_yg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[0], vl); \ - v_bb = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[1], vl); \ - v_bg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[2], vl); \ - v_br = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[3], vl); \ + v_bb = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[1] + 32, vl); \ + v_bg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[2] - 32, vl); \ + v_br = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[3] + 32, vl); \ } // Read [VLEN/8] Y, [VLEN/(8 * 2)] U and [VLEN/(8 * 2)] V from 422 @@ -485,23 +485,21 @@ void I400ToARGBRow_RVV(const uint8_t* src_y, vuint16m4_t v_yb; vuint16m4_t v_yg = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[0], vl); // To match behavior on other platforms, vxrm (fixed-point rounding mode - // register) sets to round-down mode(2). - asm volatile("csrwi vxrm, 2"); + // register) sets to round-to-nearest-up mode(0). + asm volatile("csrwi vxrm, 0"); if (is_yb_positive) { - v_yb = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[4], vl); + v_yb = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[4] - 32, vl); } else { - v_yb = __riscv_vmv_v_x_u16m4(-yuvconstants->kRGBCoeffBias[4], vl); + v_yb = __riscv_vmv_v_x_u16m4(-yuvconstants->kRGBCoeffBias[4] + 32, vl); } do { vuint8m2_t v_y, v_out; vuint16m4_t v_y_16, v_tmp0, v_tmp1, v_tmp2; - vuint32m8_t v_y1; vl = __riscv_vsetvl_e8m2(w); v_y = __riscv_vle8_v_u8m2(src_y, vl); v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); v_tmp0 = __riscv_vmul_vx_u16m4(v_y_16, 0x0101, vl); // 257 * v_y - v_y1 = __riscv_vwmulu_vv_u32m8(v_tmp0, v_yg, vl); - v_tmp1 = __riscv_vnsrl_wx_u16m4(v_y1, 16, vl); + v_tmp1 = __riscv_vmulhu_vv_u16m4(v_tmp0, v_yg, vl); if (is_yb_positive) { v_tmp2 = __riscv_vsaddu_vv_u16m4(v_tmp1, v_yb, vl); } else { -- cgit v1.2.3 From d14bd701c83375a982fe9e237a71cc06bef056e7 Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Tue, 23 May 2023 02:03:37 -0700 Subject: [RVV] Enable CopyRow_RVV, InterpolateRow_RVV, {Merge,Split}UVRow_RVV * Run on SiFive internal FPGA: MergeUVPlane_Opt(~6x vs scalar) SplitUVPlane_Opt(~6x vs scalar) TestCopyPlane(~8x vs scalar) ARGBInterpolate0_Opt(~10x vs scalar) ARGBInterpolate64_Opt(~9x vs scalar) ARGBInterpolate168_Opt(~9x vs scalar) ARGBInterpolate192_Opt(~8.5x vs scalar) ARGBInterpolate255_Opt(~8x vs scalar) Bug: libyuv:956 Change-Id: I8372341865f75f42e30371ef943d5c2e4be7b79a Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4574186 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index be4c4a30..7297a401 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -528,6 +528,75 @@ void J400ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, int width) { } while (w > 0); } +void CopyRow_RVV(const uint8_t* src, uint8_t* dst, int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m8(w); + vuint8m8_t v_data = __riscv_vle8_v_u8m8(src, vl); + __riscv_vse8_v_u8m8(dst, v_data, vl); + w -= vl; + src += vl; + dst += vl; + } while (w > 0); +} + +// Bilinear filter [VLEN/8]x2 -> [VLEN/8]x1 +void InterpolateRow_RVV(uint8_t* dst_ptr, + const uint8_t* src_ptr, + ptrdiff_t src_stride, + int dst_width, + int source_y_fraction) { + int y1_fraction = source_y_fraction; + int y0_fraction = 256 - y1_fraction; + const uint8_t* src_ptr1 = src_ptr + src_stride; + size_t dst_w = (size_t)dst_width; + assert(source_y_fraction >= 0); + assert(source_y_fraction < 256); + // Blend 100 / 0 - Copy row unchanged. + if (y1_fraction == 0) { + do { + size_t vl = __riscv_vsetvl_e8m8(dst_w); + __riscv_vse8_v_u8m8(dst_ptr, __riscv_vle8_v_u8m8(src_ptr, vl), vl); + dst_w -= vl; + src_ptr += vl; + dst_ptr += vl; + } while (dst_w > 0); + return; + } + // Blend 50 / 50. + if (y1_fraction == 128) { + do { + size_t vl = __riscv_vsetvl_e8m8(dst_w); + vuint8m8_t row0 = __riscv_vle8_v_u8m8(src_ptr, vl); + vuint8m8_t row1 = __riscv_vle8_v_u8m8(src_ptr1, vl); + // Averaging add + vuint8m8_t row_out = __riscv_vaaddu_vv_u8m8(row0, row1, vl); + __riscv_vse8_v_u8m8(dst_ptr, row_out, vl); + dst_w -= vl; + src_ptr += vl; + src_ptr1 += vl; + dst_ptr += vl; + } while (dst_w > 0); + return; + } + // General purpose row blend. + // To match behavior on other platforms, vxrm (fixed-point rounding mode + // register) is set to round-to-nearest-up(0). + asm volatile("csrwi vxrm, 0"); + do { + size_t vl = __riscv_vsetvl_e8m4(dst_w); + vuint8m4_t row0 = __riscv_vle8_v_u8m4(src_ptr, vl); + vuint16m8_t acc = __riscv_vwmulu_vx_u16m8(row0, y0_fraction, vl); + vuint8m4_t row1 = __riscv_vle8_v_u8m4(src_ptr1, vl); + acc = __riscv_vwmaccu_vx_u16m8(acc, y1_fraction, row1, vl); + __riscv_vse8_v_u8m4(dst_ptr, __riscv_vnclipu_wx_u8m4(acc, 8, vl), vl); + dst_w -= vl; + src_ptr += vl; + src_ptr1 += vl; + dst_ptr += vl; + } while (dst_w > 0); +} + void SplitRGBRow_RVV(const uint8_t* src_rgb, uint8_t* dst_r, uint8_t* dst_g, @@ -660,6 +729,42 @@ void MergeXRGBRow_RVV(const uint8_t* src_r, } while (w > 0); } +void SplitUVRow_RVV(const uint8_t* src_uv, + uint8_t* dst_u, + uint8_t* dst_v, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m4(w); + vuint8m4_t v_u, v_v; + __riscv_vlseg2e8_v_u8m4(&v_u, &v_v, src_uv, vl); + __riscv_vse8_v_u8m4(dst_u, v_u, vl); + __riscv_vse8_v_u8m4(dst_v, v_v, vl); + w -= vl; + dst_u += vl; + dst_v += vl; + src_uv += 2 * vl; + } while (w > 0); +} + +void MergeUVRow_RVV(const uint8_t* src_u, + const uint8_t* src_v, + uint8_t* dst_uv, + int width) { + size_t w = (size_t)width; + do { + vuint8m4_t v_u, v_v; + size_t vl = __riscv_vsetvl_e8m4(w); + v_u = __riscv_vle8_v_u8m4(src_u, vl); + v_v = __riscv_vle8_v_u8m4(src_v, vl); + __riscv_vsseg2e8_v_u8m4(dst_uv, v_u, v_v, vl); + w -= vl; + src_u += vl; + src_v += vl; + dst_uv += 2 * vl; + } while (w > 0); +} + struct RgbConstants { uint8_t kRGBToY[4]; uint16_t kAddY; -- cgit v1.2.3 From 4b6373d1897ce38bed4cfbd912831915942147da Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Mon, 29 May 2023 06:43:38 -0700 Subject: [RVV] Use LMUL=2 for I4{44,22}To{ARGB,RGB24,RGBA} conversion Replace vv+m1(LMUL=1) with vx+m2(LMUL=2). Some kernels' asm code might contain register spill(1~2). Change-Id: Ie3655f250d17f37c1ba9039474ece43ede98ede0 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4573159 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 247 ++++++++++++++++++++++++++---------------------------- 1 file changed, 119 insertions(+), 128 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 7297a401..27e91a3b 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -29,78 +29,76 @@ extern "C" { // Fill YUV -> RGB conversion constants into vectors // NOTE: To match behavior on other platforms, vxrm (fixed-point rounding mode // register) is set to round-to-nearest-up mode(0). -#define YUVTORGB_SETUP(yuvconst, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, \ - v_br) \ - { \ - asm volatile("csrwi vxrm, 0"); \ - vl = __riscv_vsetvl_e8m1(w); \ - v_ub = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[0], vl); \ - v_vr = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[1], vl); \ - v_ug = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[2], vl); \ - v_vg = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[3], vl); \ - v_yg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[0], vl); \ - v_bb = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[1] + 32, vl); \ - v_bg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[2] - 32, vl); \ - v_br = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[3] + 32, vl); \ +#define YUVTORGB_SETUP(vl, yuvconst, ub, vr, ug, vg, yg, bb, bg, br) \ + { \ + asm volatile("csrwi vxrm, 0"); \ + ub = yuvconst->kUVCoeff[0]; \ + vr = yuvconst->kUVCoeff[1]; \ + ug = yuvconst->kUVCoeff[2]; \ + vg = yuvconst->kUVCoeff[3]; \ + yg = yuvconst->kRGBCoeffBias[0]; \ + bb = yuvconst->kRGBCoeffBias[1] + 32; \ + bg = yuvconst->kRGBCoeffBias[2] - 32; \ + br = yuvconst->kRGBCoeffBias[3] + 32; \ } // Read [VLEN/8] Y, [VLEN/(8 * 2)] U and [VLEN/(8 * 2)] V from 422 #define READYUV422(vl, v_u, v_v, v_y_16) \ { \ - vuint8mf2_t v_tmp0, v_tmp1; \ - vuint8m1_t v_y; \ - vuint16m1_t v_u_16, v_v_16; \ - vl = __riscv_vsetvl_e8mf2((w + 1) / 2); \ - v_tmp0 = __riscv_vle8_v_u8mf2(src_u, vl); \ - v_u_16 = __riscv_vwaddu_vx_u16m1(v_tmp0, 0, vl); \ - v_tmp1 = __riscv_vle8_v_u8mf2(src_v, vl); \ - v_v_16 = __riscv_vwaddu_vx_u16m1(v_tmp1, 0, vl); \ - v_v_16 = __riscv_vmul_vx_u16m1(v_v_16, 0x0101, vl); \ - v_u_16 = __riscv_vmul_vx_u16m1(v_u_16, 0x0101, vl); \ - v_v = __riscv_vreinterpret_v_u16m1_u8m1(v_v_16); \ - v_u = __riscv_vreinterpret_v_u16m1_u8m1(v_u_16); \ - vl = __riscv_vsetvl_e8m1(w); \ - v_y = __riscv_vle8_v_u8m1(src_y, vl); \ - v_y_16 = __riscv_vwaddu_vx_u16m2(v_y, 0, vl); \ + vuint8m1_t v_tmp0, v_tmp1; \ + vuint8m2_t v_y; \ + vuint16m2_t v_u_16, v_v_16; \ + vl = __riscv_vsetvl_e8m1((w + 1) / 2); \ + v_tmp0 = __riscv_vle8_v_u8m1(src_u, vl); \ + v_u_16 = __riscv_vwaddu_vx_u16m2(v_tmp0, 0, vl); \ + v_tmp1 = __riscv_vle8_v_u8m1(src_v, vl); \ + v_v_16 = __riscv_vwaddu_vx_u16m2(v_tmp1, 0, vl); \ + v_v_16 = __riscv_vmul_vx_u16m2(v_v_16, 0x0101, vl); \ + v_u_16 = __riscv_vmul_vx_u16m2(v_u_16, 0x0101, vl); \ + v_v = __riscv_vreinterpret_v_u16m2_u8m2(v_v_16); \ + v_u = __riscv_vreinterpret_v_u16m2_u8m2(v_u_16); \ + vl = __riscv_vsetvl_e8m2(w); \ + v_y = __riscv_vle8_v_u8m2(src_y, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ } // Read [VLEN/8] Y, [VLEN/8] U, and [VLEN/8] V from 444 #define READYUV444(vl, v_u, v_v, v_y_16) \ { \ - vuint8m1_t v_y; \ - vl = __riscv_vsetvl_e8m1(w); \ - v_y = __riscv_vle8_v_u8m1(src_y, vl); \ - v_u = __riscv_vle8_v_u8m1(src_u, vl); \ - v_v = __riscv_vle8_v_u8m1(src_v, vl); \ - v_y_16 = __riscv_vwaddu_vx_u16m2(v_y, 0, vl); \ + vuint8m2_t v_y; \ + vl = __riscv_vsetvl_e8m2(w); \ + v_y = __riscv_vle8_v_u8m2(src_y, vl); \ + v_u = __riscv_vle8_v_u8m2(src_u, vl); \ + v_v = __riscv_vle8_v_u8m2(src_v, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ } // Convert from YUV to fixed point RGB -#define YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, \ - v_y_16, v_g_16, v_b_16, v_r_16) \ +#define YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, \ + v_b_16, v_r_16) \ { \ - vuint16m2_t v_tmp0, v_tmp1, v_tmp2, v_tmp3, v_tmp4; \ - vuint32m4_t v_tmp5; \ - v_tmp0 = __riscv_vwmulu_vv_u16m2(v_u, v_ug, vl); \ - v_y_16 = __riscv_vmul_vx_u16m2(v_y_16, 0x0101, vl); \ - v_tmp0 = __riscv_vwmaccu_vv_u16m2(v_tmp0, v_vg, v_v, vl); \ - v_tmp1 = __riscv_vwmulu_vv_u16m2(v_u, v_ub, vl); \ - v_tmp5 = __riscv_vwmulu_vv_u32m4(v_y_16, v_yg, vl); \ - v_tmp2 = __riscv_vnsrl_wx_u16m2(v_tmp5, 16, vl); \ - v_tmp3 = __riscv_vadd_vv_u16m2(v_tmp2, v_bg, vl); \ - v_tmp4 = __riscv_vadd_vv_u16m2(v_tmp2, v_tmp1, vl); \ - v_tmp2 = __riscv_vwmaccu_vv_u16m2(v_tmp2, v_vr, v_v, vl); \ - v_g_16 = __riscv_vssubu_vv_u16m2(v_tmp3, v_tmp0, vl); \ - v_b_16 = __riscv_vssubu_vv_u16m2(v_tmp4, v_bb, vl); \ - v_r_16 = __riscv_vssubu_vv_u16m2(v_tmp2, v_br, vl); \ + vuint16m4_t v_tmp0, v_tmp1, v_tmp2, v_tmp3, v_tmp4; \ + vuint32m8_t v_tmp5; \ + v_tmp0 = __riscv_vwmulu_vx_u16m4(v_u, ug, vl); \ + v_y_16 = __riscv_vmul_vx_u16m4(v_y_16, 0x0101, vl); \ + v_tmp0 = __riscv_vwmaccu_vx_u16m4(v_tmp0, vg, v_v, vl); \ + v_tmp1 = __riscv_vwmulu_vx_u16m4(v_u, ub, vl); \ + v_tmp5 = __riscv_vwmulu_vx_u32m8(v_y_16, yg, vl); \ + v_tmp2 = __riscv_vnsrl_wx_u16m4(v_tmp5, 16, vl); \ + v_tmp3 = __riscv_vadd_vx_u16m4(v_tmp2, bg, vl); \ + v_tmp4 = __riscv_vadd_vv_u16m4(v_tmp2, v_tmp1, vl); \ + v_tmp2 = __riscv_vwmaccu_vx_u16m4(v_tmp2, vr, v_v, vl); \ + v_g_16 = __riscv_vssubu_vv_u16m4(v_tmp3, v_tmp0, vl); \ + v_b_16 = __riscv_vssubu_vx_u16m4(v_tmp4, bb, vl); \ + v_r_16 = __riscv_vssubu_vx_u16m4(v_tmp2, br, vl); \ } // Convert from fixed point RGB To 8 bit RGB #define RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r) \ { \ - v_g = __riscv_vnclipu_wx_u8m1(v_g_16, 6, vl); \ - v_b = __riscv_vnclipu_wx_u8m1(v_b_16, 6, vl); \ - v_r = __riscv_vnclipu_wx_u8m1(v_r_16, 6, vl); \ + v_g = __riscv_vnclipu_wx_u8m2(v_g_16, 6, vl); \ + v_b = __riscv_vnclipu_wx_u8m2(v_b_16, 6, vl); \ + v_r = __riscv_vnclipu_wx_u8m2(v_r_16, 6, vl); \ } void ARGBToAR64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ar64, int width) { @@ -270,20 +268,19 @@ void I444ToARGBRow_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r, v_a; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); - v_a = __riscv_vmv_v_x_u8m1(255u, vl); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { READYUV444(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); w -= vl; src_y += vl; src_u += vl; @@ -301,20 +298,19 @@ void I444AlphaToARGBRow_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r, v_a; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV444(vl, v_u, v_v, v_y_16); - v_a = __riscv_vle8_v_u8m1(src_a, vl); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + v_a = __riscv_vle8_v_u8m2(src_a, vl); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); w -= vl; src_y += vl; src_a += vl; @@ -332,19 +328,18 @@ void I444ToRGB24Row_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV444(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg3e8_v_u8m1(dst_rgb24, v_b, v_g, v_r, vl); + __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); w -= vl; src_y += vl; src_u += vl; @@ -361,20 +356,19 @@ void I422ToARGBRow_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r, v_a; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); - v_a = __riscv_vmv_v_x_u8m1(255u, vl); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { READYUV422(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); w -= vl; src_y += vl; src_u += vl / 2; @@ -392,20 +386,19 @@ void I422AlphaToARGBRow_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r, v_a; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV422(vl, v_u, v_v, v_y_16); - v_a = __riscv_vle8_v_u8m1(src_a, vl); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + v_a = __riscv_vle8_v_u8m2(src_a, vl); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg4e8_v_u8m1(dst_argb, v_b, v_g, v_r, v_a, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); w -= vl; src_y += vl; src_a += vl; @@ -423,20 +416,19 @@ void I422ToRGBARow_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r, v_a; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); - v_a = __riscv_vmv_v_x_u8m1(255u, vl); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { READYUV422(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg4e8_v_u8m1(dst_rgba, v_a, v_b, v_g, v_r, vl); + __riscv_vsseg4e8_v_u8m2(dst_rgba, v_a, v_b, v_g, v_r, vl); w -= vl; src_y += vl; src_u += vl / 2; @@ -453,19 +445,18 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, int width) { size_t vl; size_t w = (size_t)width; - vuint8m1_t v_u, v_v; - vuint8m1_t v_ub, v_vr, v_ug, v_vg; - vuint8m1_t v_b, v_g, v_r; - vuint16m2_t v_yg, v_bb, v_bg, v_br; - vuint16m2_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(yuvconstants, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, - v_br); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV422(vl, v_u, v_v, v_y_16); - YUVTORGB(vl, v_u, v_v, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, v_br, - v_y_16, v_g_16, v_b_16, v_r_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); - __riscv_vsseg3e8_v_u8m1(dst_rgb24, v_b, v_g, v_r, vl); + __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); w -= vl; src_y += vl; src_u += vl / 2; -- cgit v1.2.3 From 04821d1e7d60845525e8db55c7bcd41ef5be9406 Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Thu, 15 Jun 2023 04:56:58 -0700 Subject: [RVV] Enable ARGBExtractAlphaRow/ARGBCopyYToAlphaRow * Run on SiFive internal FPGA: TestARGBExtractAlpha(~3.2x vs scalar) TestARGBCopyYToAlpha(~1.6x vs scalar) Change-Id: I36525c67e8ac3f71ea9d1a58c7dc15a4009d9da1 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4617955 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 27e91a3b..a79560c7 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -948,6 +948,35 @@ void ARGBAttenuateRow_RVV(const uint8_t* src_argb, } while (w > 0); } +void ARGBExtractAlphaRow_RVV(const uint8_t* src_argb, + uint8_t* dst_a, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_b, v_g, v_r, v_a; + __riscv_vlseg4e8_v_u8m2(&v_r, &v_g, &v_b, &v_a, src_argb, vl); + __riscv_vse8_v_u8m2(dst_a, v_a, vl); + w -= vl; + src_argb += vl * 4; + dst_a += vl; + } while (w > 0); +} + +void ARGBCopyYToAlphaRow_RVV(const uint8_t* src, uint8_t* dst, int width) { + size_t w = (size_t)width; + const ptrdiff_t dst_stride = 4; + dst += 3; + do { + size_t vl = __riscv_vsetvl_e8m8(w); + vuint8m8_t v_a = __riscv_vle8_v_u8m8(src, vl); + __riscv_vsse8_v_u8m8(dst, dst_stride, v_a, vl); + w -= vl; + src += vl; + dst += vl * dst_stride; + } while (w > 0); +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv -- cgit v1.2.3 From 7939e039e76072bc687128fc5c1f10fe04f7858c Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Fri, 16 Jun 2023 00:12:24 -0700 Subject: [RVV] Fix compile warning in row_rvv 1. Fix compile warning in row_rvv.cc 2. Avoid compile row_rvv.cc/scale_rvv.cc when using GCC There is no RVV segment load & store on GCC. Hence, avoid compiling rvv code on GCC temporarily. 3. Add several compile options to cmake build flow -Wno-sign-compare -Wno-unused-function -Wunused-variable -Wuninitialized Bug: libyuv:956 Change-Id: I9577f98190fc9b28fb6fde65d82d0c67ce54f9ee Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4615441 Commit-Queue: Frank Barchard Reviewed-by: Frank Barchard --- source/row_rvv.cc | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index a79560c7..29422574 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -17,7 +17,8 @@ #include "libyuv/row.h" -#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) +// This module is for clang rvv. GCC hasn't supported segment load & store. +#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) && defined(__clang__) #include #include @@ -29,17 +30,17 @@ extern "C" { // Fill YUV -> RGB conversion constants into vectors // NOTE: To match behavior on other platforms, vxrm (fixed-point rounding mode // register) is set to round-to-nearest-up mode(0). -#define YUVTORGB_SETUP(vl, yuvconst, ub, vr, ug, vg, yg, bb, bg, br) \ - { \ - asm volatile("csrwi vxrm, 0"); \ - ub = yuvconst->kUVCoeff[0]; \ - vr = yuvconst->kUVCoeff[1]; \ - ug = yuvconst->kUVCoeff[2]; \ - vg = yuvconst->kUVCoeff[3]; \ - yg = yuvconst->kRGBCoeffBias[0]; \ - bb = yuvconst->kRGBCoeffBias[1] + 32; \ - bg = yuvconst->kRGBCoeffBias[2] - 32; \ - br = yuvconst->kRGBCoeffBias[3] + 32; \ +#define YUVTORGB_SETUP(yuvconst, ub, vr, ug, vg, yg, bb, bg, br) \ + { \ + asm volatile("csrwi vxrm, 0"); \ + ub = yuvconst->kUVCoeff[0]; \ + vr = yuvconst->kUVCoeff[1]; \ + ug = yuvconst->kUVCoeff[2]; \ + vg = yuvconst->kUVCoeff[3]; \ + yg = yuvconst->kRGBCoeffBias[0]; \ + bb = yuvconst->kRGBCoeffBias[1] + 32; \ + bg = yuvconst->kRGBCoeffBias[2] - 32; \ + br = yuvconst->kRGBCoeffBias[3] + 32; \ } // Read [VLEN/8] Y, [VLEN/(8 * 2)] U and [VLEN/(8 * 2)] V from 422 @@ -266,14 +267,14 @@ void I444ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, const struct YuvConstants* yuvconstants, int width) { - size_t vl; size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); uint8_t ub, vr, ug, vg; int16_t yg, bb, bg, br; vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { READYUV444(vl, v_u, v_v, v_y_16); @@ -303,7 +304,7 @@ void I444AlphaToARGBRow_RVV(const uint8_t* src_y, vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV444(vl, v_u, v_v, v_y_16); v_a = __riscv_vle8_v_u8m2(src_a, vl); @@ -333,7 +334,7 @@ void I444ToRGB24Row_RVV(const uint8_t* src_y, vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV444(vl, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, @@ -354,14 +355,14 @@ void I422ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, const struct YuvConstants* yuvconstants, int width) { - size_t vl; size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); uint8_t ub, vr, ug, vg; int16_t yg, bb, bg, br; vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { READYUV422(vl, v_u, v_v, v_y_16); @@ -391,7 +392,7 @@ void I422AlphaToARGBRow_RVV(const uint8_t* src_y, vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV422(vl, v_u, v_v, v_y_16); v_a = __riscv_vle8_v_u8m2(src_a, vl); @@ -414,14 +415,14 @@ void I422ToRGBARow_RVV(const uint8_t* src_y, uint8_t* dst_rgba, const struct YuvConstants* yuvconstants, int width) { - size_t vl; size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); uint8_t ub, vr, ug, vg; int16_t yg, bb, bg, br; vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { READYUV422(vl, v_u, v_v, v_y_16); @@ -450,7 +451,7 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, vuint8m2_t v_u, v_v; vuint8m2_t v_b, v_g, v_r; vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; - YUVTORGB_SETUP(vl, yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { READYUV422(vl, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, @@ -982,4 +983,4 @@ void ARGBCopyYToAlphaRow_RVV(const uint8_t* src, uint8_t* dst, int width) { } // namespace libyuv #endif -#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) +#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) && defined(__clang__) -- cgit v1.2.3 From 4472b5b8491189ca173b5eb771a25855cf5f6ed9 Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Fri, 16 Jun 2023 19:09:17 -0700 Subject: [RVV] Update ARGBAttenuateRow_RVV implementation Bug: libyuv:956 Change-Id: Ib539c2196767e88fa6e419ed2f22d95b6deaf406 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4623172 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 29422574..bbb54a1b 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -924,24 +924,31 @@ void RAWToYRow_RVV(const uint8_t* src_raw, uint8_t* dst_y, int width) { RGBToYMatrixRow_RVV(src_raw, dst_y, width, &kRawI601Constants); } +// Attenuate: (f * a + 255) >> 8 void ARGBAttenuateRow_RVV(const uint8_t* src_argb, uint8_t* dst_argb, int width) { size_t w = (size_t)width; // To match behavior on other platforms, vxrm (fixed-point rounding mode - // register) is set to round-to-nearest-up(0). - asm volatile("csrwi vxrm, 0"); + // register) is set to round-down(2). + asm volatile("csrwi vxrm, 2"); do { vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_ba_16, v_ga_16, v_ra_16; size_t vl = __riscv_vsetvl_e8m2(w); __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + // f * a v_ba_16 = __riscv_vwmulu_vv_u16m4(v_b, v_a, vl); v_ga_16 = __riscv_vwmulu_vv_u16m4(v_g, v_a, vl); v_ra_16 = __riscv_vwmulu_vv_u16m4(v_r, v_a, vl); - v_b = __riscv_vnclipu_wx_u8m2(v_ba_16, 8, vl); - v_g = __riscv_vnclipu_wx_u8m2(v_ga_16, 8, vl); - v_r = __riscv_vnclipu_wx_u8m2(v_ra_16, 8, vl); + // f * a + 255 + v_ba_16 = __riscv_vadd_vx_u16m4(v_ba_16, 255u, vl); + v_ga_16 = __riscv_vadd_vx_u16m4(v_ga_16, 255u, vl); + v_ra_16 = __riscv_vadd_vx_u16m4(v_ra_16, 255u, vl); + // (f * a + 255) >> 8 + v_b = __riscv_vnsrl_wx_u8m2(v_ba_16, 8, vl); + v_g = __riscv_vnsrl_wx_u8m2(v_ga_16, 8, vl); + v_r = __riscv_vnsrl_wx_u8m2(v_ra_16, 8, vl); __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); w -= vl; src_argb += vl * 4; -- cgit v1.2.3 From 873d0db98964e90607c6ac5af07ff97a48665133 Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Sun, 18 Jun 2023 04:54:00 -0700 Subject: [RVV] Fix TestARGBInterpolate test fail Root cause: Because InterpolateRow_RVV doesn't setup rounding mode to round-to-nearest-up when y1_fraction == 128. The rounding mode register is set to round-down in ARGBAttenuateRow_RVV. It cause InterpolateRow_RVV(y1_fraction == 128) runs on round-down mode. Running on round-down mode make output result differs from round-to-nearest-up mode. Solved by: ensure to use correct rounding mode in InterpolateRow_RVV. Also, removing unnecessary rounding mode setup in ARGBAttenuateRow_RVV. Bug: libyuv:956 Change-Id: Ib5265d42bad76b036e42b8f91ee42a9afe1f768d Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4624492 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index bbb54a1b..4a3e8809 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -555,13 +555,16 @@ void InterpolateRow_RVV(uint8_t* dst_ptr, } while (dst_w > 0); return; } + // To match behavior on other platforms, vxrm (fixed-point rounding mode + // register) is set to round-to-nearest-up(0). + asm volatile("csrwi vxrm, 0"); // Blend 50 / 50. if (y1_fraction == 128) { do { size_t vl = __riscv_vsetvl_e8m8(dst_w); vuint8m8_t row0 = __riscv_vle8_v_u8m8(src_ptr, vl); vuint8m8_t row1 = __riscv_vle8_v_u8m8(src_ptr1, vl); - // Averaging add + // Use round-to-nearest-up mode for averaging add vuint8m8_t row_out = __riscv_vaaddu_vv_u8m8(row0, row1, vl); __riscv_vse8_v_u8m8(dst_ptr, row_out, vl); dst_w -= vl; @@ -572,15 +575,13 @@ void InterpolateRow_RVV(uint8_t* dst_ptr, return; } // General purpose row blend. - // To match behavior on other platforms, vxrm (fixed-point rounding mode - // register) is set to round-to-nearest-up(0). - asm volatile("csrwi vxrm, 0"); do { size_t vl = __riscv_vsetvl_e8m4(dst_w); vuint8m4_t row0 = __riscv_vle8_v_u8m4(src_ptr, vl); vuint16m8_t acc = __riscv_vwmulu_vx_u16m8(row0, y0_fraction, vl); vuint8m4_t row1 = __riscv_vle8_v_u8m4(src_ptr1, vl); acc = __riscv_vwmaccu_vx_u16m8(acc, y1_fraction, row1, vl); + // Use round-to-nearest-up mode for vnclip __riscv_vse8_v_u8m4(dst_ptr, __riscv_vnclipu_wx_u8m4(acc, 8, vl), vl); dst_w -= vl; src_ptr += vl; @@ -929,9 +930,6 @@ void ARGBAttenuateRow_RVV(const uint8_t* src_argb, uint8_t* dst_argb, int width) { size_t w = (size_t)width; - // To match behavior on other platforms, vxrm (fixed-point rounding mode - // register) is set to round-down(2). - asm volatile("csrwi vxrm, 2"); do { vuint8m2_t v_b, v_g, v_r, v_a; vuint16m4_t v_ba_16, v_ga_16, v_ra_16; -- cgit v1.2.3 From a34a0ba68781d0d1914597449d871775dad50984 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Mon, 26 Jun 2023 12:16:37 -0700 Subject: ARGBExtractAlpha rename variables to match format Bug: libyuv:956 Change-Id: I31070791754fc69b72c6dcc61be2e038d2676ed9 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4646636 Reviewed-by: Wan-Teh Chang --- source/row_rvv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index 4a3e8809..b49e5b1b 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -961,7 +961,7 @@ void ARGBExtractAlphaRow_RVV(const uint8_t* src_argb, do { size_t vl = __riscv_vsetvl_e8m2(w); vuint8m2_t v_b, v_g, v_r, v_a; - __riscv_vlseg4e8_v_u8m2(&v_r, &v_g, &v_b, &v_a, src_argb, vl); + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); __riscv_vse8_v_u8m2(dst_a, v_a, vl); w -= vl; src_argb += vl * 4; -- cgit v1.2.3 From 650be7496fe171cc0d93935a4c161d45101533f4 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Thu, 29 Jun 2023 22:53:42 -0700 Subject: Fix warnings for missing prototypes - Add static to internal scale and rotate functions - Remove unittest that tested an internal scale function - Remove unused private functions - Include missing scale_argb.h header - Bump version and apply clang format Bug: libyuv:830 Change-Id: I45bab0423b86334f9707f935aedd0c6efc442dd4 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4658956 Reviewed-by: Mirko Bonadei --- source/row_rvv.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index b49e5b1b..ad5ccbcd 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -18,7 +18,8 @@ #include "libyuv/row.h" // This module is for clang rvv. GCC hasn't supported segment load & store. -#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) && defined(__clang__) +#if !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) && \ + defined(__clang__) #include #include @@ -988,4 +989,5 @@ void ARGBCopyYToAlphaRow_RVV(const uint8_t* src, uint8_t* dst, int width) { } // namespace libyuv #endif -#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) && defined(__clang__) +#endif // !defined(LIBYUV_DISABLE_RVV) && defined(__riscv_vector) && + // defined(__clang__) -- cgit v1.2.3 From aed6dbef176815fb4186dddb73f6d753ef19073a Mon Sep 17 00:00:00 2001 From: Darren Hsieh Date: Thu, 13 Jul 2023 00:23:11 -0700 Subject: [RVV] Enable NV{12,21}To{ARGB,RGB24}Row_RVV * Run on SiFive internal FPGA(w/ -march=rv64gcv): Test Case Speedup NV12ToARGB_Opt 12.0 NV21ToARGB_Opt 12.1 NV12ToABGR_Opt 12.6 NV21ToABGR_Opt 12.0 NV12ToRGB24_Opt 12.5 NV21ToRGB24_Opt 11.7 NV12ToRAW_Opt 12.1 NV21ToRAW_Opt 11.4 Change-Id: Icae2bac2b4ebbd4c5a89e847fde9a74fe6481878 Signed-off-by: Darren Hsieh Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4707804 Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- source/row_rvv.cc | 212 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 178 insertions(+), 34 deletions(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index ad5ccbcd..c8df61db 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -44,35 +44,35 @@ extern "C" { br = yuvconst->kRGBCoeffBias[3] + 32; \ } -// Read [VLEN/8] Y, [VLEN/(8 * 2)] U and [VLEN/(8 * 2)] V from 422 -#define READYUV422(vl, v_u, v_v, v_y_16) \ - { \ - vuint8m1_t v_tmp0, v_tmp1; \ - vuint8m2_t v_y; \ - vuint16m2_t v_u_16, v_v_16; \ - vl = __riscv_vsetvl_e8m1((w + 1) / 2); \ - v_tmp0 = __riscv_vle8_v_u8m1(src_u, vl); \ - v_u_16 = __riscv_vwaddu_vx_u16m2(v_tmp0, 0, vl); \ - v_tmp1 = __riscv_vle8_v_u8m1(src_v, vl); \ - v_v_16 = __riscv_vwaddu_vx_u16m2(v_tmp1, 0, vl); \ - v_v_16 = __riscv_vmul_vx_u16m2(v_v_16, 0x0101, vl); \ - v_u_16 = __riscv_vmul_vx_u16m2(v_u_16, 0x0101, vl); \ - v_v = __riscv_vreinterpret_v_u16m2_u8m2(v_v_16); \ - v_u = __riscv_vreinterpret_v_u16m2_u8m2(v_u_16); \ - vl = __riscv_vsetvl_e8m2(w); \ - v_y = __riscv_vle8_v_u8m2(src_y, vl); \ - v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ +// Read [2*VLEN/8] Y, [VLEN/8] U and [VLEN/8] V from 422 +#define READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16) \ + { \ + vuint8m1_t v_tmp0, v_tmp1; \ + vuint8m2_t v_y; \ + vuint16m2_t v_u_16, v_v_16; \ + vl = __riscv_vsetvl_e8m1((w + 1) / 2); \ + v_tmp0 = __riscv_vle8_v_u8m1(src_u, vl); \ + v_u_16 = __riscv_vwaddu_vx_u16m2(v_tmp0, 0, vl); \ + v_tmp1 = __riscv_vle8_v_u8m1(src_v, vl); \ + v_v_16 = __riscv_vwaddu_vx_u16m2(v_tmp1, 0, vl); \ + v_v_16 = __riscv_vmul_vx_u16m2(v_v_16, 0x0101, vl); \ + v_u_16 = __riscv_vmul_vx_u16m2(v_u_16, 0x0101, vl); \ + v_v = __riscv_vreinterpret_v_u16m2_u8m2(v_v_16); \ + v_u = __riscv_vreinterpret_v_u16m2_u8m2(v_u_16); \ + vl = __riscv_vsetvl_e8m2(w); \ + v_y = __riscv_vle8_v_u8m2(src_y, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ } -// Read [VLEN/8] Y, [VLEN/8] U, and [VLEN/8] V from 444 -#define READYUV444(vl, v_u, v_v, v_y_16) \ - { \ - vuint8m2_t v_y; \ - vl = __riscv_vsetvl_e8m2(w); \ - v_y = __riscv_vle8_v_u8m2(src_y, vl); \ - v_u = __riscv_vle8_v_u8m2(src_u, vl); \ - v_v = __riscv_vle8_v_u8m2(src_v, vl); \ - v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ +// Read [2*VLEN/8] Y, [2*VLEN/8] U, and [2*VLEN/8] V from 444 +#define READYUV444(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16) \ + { \ + vuint8m2_t v_y; \ + vl = __riscv_vsetvl_e8m2(w); \ + v_y = __riscv_vle8_v_u8m2(src_y, vl); \ + v_u = __riscv_vle8_v_u8m2(src_u, vl); \ + v_v = __riscv_vle8_v_u8m2(src_v, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ } // Convert from YUV to fixed point RGB @@ -103,6 +103,44 @@ extern "C" { v_r = __riscv_vnclipu_wx_u8m2(v_r_16, 6, vl); \ } +// Read [2*VLEN/8] Y from src_y; Read [VLEN/8] U and [VLEN/8] V from src_uv +#define READNV12(vl, w, src_y, src_uv, v_u, v_v, v_y_16) \ + { \ + vuint8m1_t v_tmp0, v_tmp1; \ + vuint8m2_t v_y; \ + vuint16m2_t v_u_16, v_v_16; \ + vl = __riscv_vsetvl_e8m1((w + 1) / 2); \ + __riscv_vlseg2e8_v_u8m1(&v_tmp0, &v_tmp1, src_uv, vl); \ + v_u_16 = __riscv_vwaddu_vx_u16m2(v_tmp0, 0, vl); \ + v_v_16 = __riscv_vwaddu_vx_u16m2(v_tmp1, 0, vl); \ + v_v_16 = __riscv_vmul_vx_u16m2(v_v_16, 0x0101, vl); \ + v_u_16 = __riscv_vmul_vx_u16m2(v_u_16, 0x0101, vl); \ + v_v = __riscv_vreinterpret_v_u16m2_u8m2(v_v_16); \ + v_u = __riscv_vreinterpret_v_u16m2_u8m2(v_u_16); \ + vl = __riscv_vsetvl_e8m2(w); \ + v_y = __riscv_vle8_v_u8m2(src_y, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ + } + +// Read 2*[VLEN/8] Y from src_y; Read [VLEN/8] U and [VLEN/8] V from src_vu +#define READNV21(vl, w, src_y, src_vu, v_u, v_v, v_y_16) \ + { \ + vuint8m1_t v_tmp0, v_tmp1; \ + vuint8m2_t v_y; \ + vuint16m2_t v_u_16, v_v_16; \ + vl = __riscv_vsetvl_e8m1((w + 1) / 2); \ + __riscv_vlseg2e8_v_u8m1(&v_tmp0, &v_tmp1, src_vu, vl); \ + v_u_16 = __riscv_vwaddu_vx_u16m2(v_tmp1, 0, vl); \ + v_v_16 = __riscv_vwaddu_vx_u16m2(v_tmp0, 0, vl); \ + v_v_16 = __riscv_vmul_vx_u16m2(v_v_16, 0x0101, vl); \ + v_u_16 = __riscv_vmul_vx_u16m2(v_u_16, 0x0101, vl); \ + v_v = __riscv_vreinterpret_v_u16m2_u8m2(v_v_16); \ + v_u = __riscv_vreinterpret_v_u16m2_u8m2(v_u_16); \ + vl = __riscv_vsetvl_e8m2(w); \ + v_y = __riscv_vle8_v_u8m2(src_y, vl); \ + v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ + } + void ARGBToAR64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ar64, int width) { size_t avl = (size_t)4 * width; do { @@ -278,7 +316,7 @@ void I444ToARGBRow_RVV(const uint8_t* src_y, YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { - READYUV444(vl, v_u, v_v, v_y_16); + READYUV444(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); @@ -307,7 +345,7 @@ void I444AlphaToARGBRow_RVV(const uint8_t* src_y, vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { - READYUV444(vl, v_u, v_v, v_y_16); + READYUV444(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); v_a = __riscv_vle8_v_u8m2(src_a, vl); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); @@ -337,7 +375,7 @@ void I444ToRGB24Row_RVV(const uint8_t* src_y, vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { - READYUV444(vl, v_u, v_v, v_y_16); + READYUV444(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); @@ -366,7 +404,7 @@ void I422ToARGBRow_RVV(const uint8_t* src_y, YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { - READYUV422(vl, v_u, v_v, v_y_16); + READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); @@ -395,7 +433,7 @@ void I422AlphaToARGBRow_RVV(const uint8_t* src_y, vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { - READYUV422(vl, v_u, v_v, v_y_16); + READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); v_a = __riscv_vle8_v_u8m2(src_a, vl); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); @@ -426,7 +464,7 @@ void I422ToRGBARow_RVV(const uint8_t* src_y, YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); v_a = __riscv_vmv_v_x_u8m2(255u, vl); do { - READYUV422(vl, v_u, v_v, v_y_16); + READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); @@ -454,7 +492,7 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); do { - READYUV422(vl, v_u, v_v, v_y_16); + READYUV422(vl, w, src_y, src_u, src_v, v_u, v_v, v_y_16); YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, v_b_16, v_r_16); RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); @@ -533,6 +571,112 @@ void CopyRow_RVV(const uint8_t* src, uint8_t* dst, int width) { } while (w > 0); } +void NV12ToARGBRow_RVV(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + v_a = __riscv_vmv_v_x_u8m2(255u, vl); + do { + READNV12(vl, w, src_y, src_uv, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_y += vl; + src_uv += vl; + dst_argb += vl * 4; + } while (w > 0); +} + +void NV12ToRGB24Row_RVV(const uint8_t* src_y, + const uint8_t* src_uv, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + do { + READNV12(vl, w, src_y, src_uv, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); + w -= vl; + src_y += vl; + src_uv += vl; + dst_rgb24 += vl * 3; + } while (w > 0); +} + +void NV21ToARGBRow_RVV(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_argb, + const struct YuvConstants* yuvconstants, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r, v_a; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + v_a = __riscv_vmv_v_x_u8m2(255u, vl); + do { + READNV21(vl, w, src_y, src_vu, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_y += vl; + src_vu += vl; + dst_argb += vl * 4; + } while (w > 0); +} + +void NV21ToRGB24Row_RVV(const uint8_t* src_y, + const uint8_t* src_vu, + uint8_t* dst_rgb24, + const struct YuvConstants* yuvconstants, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvl_e8m2(w); + uint8_t ub, vr, ug, vg; + int16_t yg, bb, bg, br; + vuint8m2_t v_u, v_v; + vuint8m2_t v_b, v_g, v_r; + vuint16m4_t v_y_16, v_g_16, v_b_16, v_r_16; + YUVTORGB_SETUP(yuvconstants, ub, vr, ug, vg, yg, bb, bg, br); + do { + READNV21(vl, w, src_y, src_vu, v_u, v_v, v_y_16); + YUVTORGB(vl, v_u, v_v, ub, vr, ug, vg, yg, bb, bg, br, v_y_16, v_g_16, + v_b_16, v_r_16); + RGBTORGB8(vl, v_g_16, v_b_16, v_r_16, v_g, v_b, v_r); + __riscv_vsseg3e8_v_u8m2(dst_rgb24, v_b, v_g, v_r, vl); + w -= vl; + src_y += vl; + src_vu += vl; + dst_rgb24 += vl * 3; + } while (w > 0); +} + // Bilinear filter [VLEN/8]x2 -> [VLEN/8]x1 void InterpolateRow_RVV(uint8_t* dst_ptr, const uint8_t* src_ptr, -- cgit v1.2.3 From d33edd237313a03a06210dfa392c6c961d769a6c Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Fri, 7 Jul 2023 05:09:34 -0700 Subject: [RVV] Enable ARGBBlendRow_RVV/BlendPlaneRow_RVV * Run on SiFive internal FPGA: Test case Speedup ARGBBlend_Opt 4.60 BlendPlane_Opt 5.96 I420Blend_Opt 5.83 - Also, add code to use ScaleRowDown2Box_RVV in I420Blend Change-Id: Icc75e05d26b3427a98269d2a33c4474074033264 Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4681100 Reviewed-by: Frank Barchard Reviewed-by: Wan-Teh Chang Commit-Queue: Frank Barchard --- source/row_rvv.cc | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index c8df61db..f99a6410 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -1070,6 +1070,81 @@ void RAWToYRow_RVV(const uint8_t* src_raw, uint8_t* dst_y, int width) { RGBToYMatrixRow_RVV(src_raw, dst_y, width, &kRawI601Constants); } +// Blend src_argb over src_argb1 and store to dst_argb. +// dst_argb may be src_argb or src_argb1. +// src_argb: RGB values have already been pre-multiplied by the a. +void ARGBBlendRow_RVV(const uint8_t* src_argb, + const uint8_t* src_argb1, + uint8_t* dst_argb, + int width) { + size_t w = (size_t)width; + size_t vl = __riscv_vsetvlmax_e8m2(); + // clamp255((((256 - a) * b) >> 8) + f) + // = b * (256 - a) / 256 + f + // = b - (b * a / 256) + f + vuint8m2_t v_255 = __riscv_vmv_v_x_u8m2(255, vl); + do { + vuint8m2_t v_src0_b, v_src0_g, v_src0_r, v_src0_a; + vuint8m2_t v_src1_b, v_src1_g, v_src1_r, v_src1_a; + vuint8m2_t v_tmp_b, v_tmp_g, v_tmp_r; + vuint8m2_t v_dst_b, v_dst_g, v_dst_r; + vl = __riscv_vsetvl_e8m2(w); + __riscv_vlseg4e8_v_u8m2(&v_src0_b, &v_src0_g, &v_src0_r, &v_src0_a, + src_argb, vl); + __riscv_vlseg4e8_v_u8m2(&v_src1_b, &v_src1_g, &v_src1_r, &v_src1_a, + src_argb1, vl); + + v_tmp_b = __riscv_vmulhu_vv_u8m2(v_src1_b, v_src0_a, vl); + v_tmp_g = __riscv_vmulhu_vv_u8m2(v_src1_g, v_src0_a, vl); + v_tmp_r = __riscv_vmulhu_vv_u8m2(v_src1_r, v_src0_a, vl); + + v_dst_b = __riscv_vsub_vv_u8m2(v_src1_b, v_tmp_b, vl); + v_dst_g = __riscv_vsub_vv_u8m2(v_src1_g, v_tmp_g, vl); + v_dst_r = __riscv_vsub_vv_u8m2(v_src1_r, v_tmp_r, vl); + + v_dst_b = __riscv_vsaddu_vv_u8m2(v_dst_b, v_src0_b, vl); + v_dst_g = __riscv_vsaddu_vv_u8m2(v_dst_g, v_src0_g, vl); + v_dst_r = __riscv_vsaddu_vv_u8m2(v_dst_r, v_src0_r, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_dst_b, v_dst_g, v_dst_r, v_255, vl); + + w -= vl; + src_argb += 4 * vl; + src_argb1 += 4 * vl; + dst_argb += 4 * vl; + } while (w > 0); +} + +void BlendPlaneRow_RVV(const uint8_t* src0, + const uint8_t* src1, + const uint8_t* alpha, + uint8_t* dst, + int width) { + size_t w = (size_t)width; + do { + vuint16m8_t v_dst_u16; + vuint8m4_t v_dst; + size_t vl = __riscv_vsetvl_e8m4(w); + vuint8m4_t v_src0 = __riscv_vle8_v_u8m4(src0, vl); + vuint8m4_t v_src1 = __riscv_vle8_v_u8m4(src1, vl); + vuint8m4_t v_alpha = __riscv_vle8_v_u8m4(alpha, vl); + vuint8m4_t v_255_minus_alpha = __riscv_vrsub_vx_u8m4(v_alpha, 255u, vl); + + // (a * foreground) + (1-a) * background + v_dst_u16 = __riscv_vwmulu_vv_u16m8(v_alpha, v_src0, vl); + v_dst_u16 = + __riscv_vwmaccu_vv_u16m8(v_dst_u16, v_255_minus_alpha, v_src1, vl); + v_dst_u16 = __riscv_vadd_vx_u16m8(v_dst_u16, 255u, vl); + v_dst = __riscv_vnsrl_wx_u8m4(v_dst_u16, 8, vl); + + __riscv_vse8_v_u8m4(dst, v_dst, vl); + w -= vl; + src0 += vl; + src1 += vl; + alpha += vl; + dst += vl; + } while (w > 0); +} + // Attenuate: (f * a + 255) >> 8 void ARGBAttenuateRow_RVV(const uint8_t* src_argb, uint8_t* dst_argb, -- cgit v1.2.3 From 696e61957172a89691249e91c6e8c9d7f0b7e6fc Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Thu, 3 Aug 2023 19:03:55 -0700 Subject: RVV check __riscv_v_intrinsic version Bug: libyuv:965 Change-Id: I9b02abd13ab3345288655fa7a16383f59cf66bb8 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4750230 Commit-Queue: Frank Barchard Reviewed-by: Mirko Bonadei --- source/row_rvv.cc | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index f99a6410..c875be2f 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -141,6 +141,7 @@ extern "C" { v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl); \ } +#ifdef HAS_ARGBTOAR64ROW_RVV void ARGBToAR64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ar64, int width) { size_t avl = (size_t)4 * width; do { @@ -156,7 +157,9 @@ void ARGBToAR64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ar64, int width) { dst_ar64 += vl; } while (avl > 0); } +#endif +#ifdef HAS_ARGBTOAB64ROW_RVV void ARGBToAB64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ab64, int width) { size_t avl = (size_t)width; do { @@ -178,7 +181,9 @@ void ARGBToAB64Row_RVV(const uint8_t* src_argb, uint16_t* dst_ab64, int width) { dst_ab64 += 4 * vl; } while (avl > 0); } +#endif +#ifdef HAS_AR64TOARGBROW_RVV void AR64ToARGBRow_RVV(const uint16_t* src_ar64, uint8_t* dst_argb, int width) { size_t avl = (size_t)4 * width; do { @@ -193,7 +198,9 @@ void AR64ToARGBRow_RVV(const uint16_t* src_ar64, uint8_t* dst_argb, int width) { dst_argb += vl; } while (avl > 0); } +#endif +#ifdef HAS_AB64TOARGBROW_RVV void AB64ToARGBRow_RVV(const uint16_t* src_ab64, uint8_t* dst_argb, int width) { size_t avl = (size_t)width; do { @@ -211,7 +218,9 @@ void AB64ToARGBRow_RVV(const uint16_t* src_ab64, uint8_t* dst_argb, int width) { dst_argb += 4 * vl; } while (avl > 0); } +#endif +#ifdef HAS_RAWTOARGBROW_RVV void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { size_t w = (size_t)width; size_t vl = __riscv_vsetvl_e8m2(w); @@ -226,7 +235,9 @@ void RAWToARGBRow_RVV(const uint8_t* src_raw, uint8_t* dst_argb, int width) { vl = __riscv_vsetvl_e8m2(w); } while (w > 0); } +#endif +#ifdef HAS_RAWTORGBAROW_RVV void RAWToRGBARow_RVV(const uint8_t* src_raw, uint8_t* dst_rgba, int width) { size_t w = (size_t)width; size_t vl = __riscv_vsetvl_e8m2(w); @@ -241,7 +252,9 @@ void RAWToRGBARow_RVV(const uint8_t* src_raw, uint8_t* dst_rgba, int width) { vl = __riscv_vsetvl_e8m2(w); } while (w > 0); } +#endif +#ifdef HAS_RAWTORGB24ROW_RVV void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { size_t w = (size_t)width; do { @@ -254,7 +267,9 @@ void RAWToRGB24Row_RVV(const uint8_t* src_raw, uint8_t* dst_rgb24, int width) { dst_rgb24 += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_ARGBTORAWROW_RVV void ARGBToRAWRow_RVV(const uint8_t* src_argb, uint8_t* dst_raw, int width) { size_t w = (size_t)width; do { @@ -267,7 +282,9 @@ void ARGBToRAWRow_RVV(const uint8_t* src_argb, uint8_t* dst_raw, int width) { dst_raw += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_ARGBTORGB24ROW_RVV void ARGBToRGB24Row_RVV(const uint8_t* src_argb, uint8_t* dst_rgb24, int width) { @@ -282,7 +299,9 @@ void ARGBToRGB24Row_RVV(const uint8_t* src_argb, dst_rgb24 += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_RGB24TOARGBROW_RVV void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_argb, int width) { @@ -299,7 +318,9 @@ void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, vl = __riscv_vsetvl_e8m2(w); } while (w > 0); } +#endif +#ifdef HAS_I444TOARGBROW_RVV void I444ToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -328,7 +349,9 @@ void I444ToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_I444ALPHATOARGBROW_RVV void I444AlphaToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -359,7 +382,9 @@ void I444AlphaToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_I444TORGB24ROW_RVV void I444ToRGB24Row_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -387,7 +412,9 @@ void I444ToRGB24Row_RVV(const uint8_t* src_y, dst_rgb24 += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_I422TOARGBROW_RVV void I422ToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -416,7 +443,9 @@ void I422ToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_I422ALPHATOARGBROW_RVV void I422AlphaToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -447,7 +476,9 @@ void I422AlphaToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_I422TORGBAROW_RVV void I422ToRGBARow_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -476,7 +507,9 @@ void I422ToRGBARow_RVV(const uint8_t* src_y, dst_rgba += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_I422TORGB24ROW_RVV void I422ToRGB24Row_RVV(const uint8_t* src_y, const uint8_t* src_u, const uint8_t* src_v, @@ -504,7 +537,9 @@ void I422ToRGB24Row_RVV(const uint8_t* src_y, dst_rgb24 += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_I400TOARGBROW_RVV void I400ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, const struct YuvConstants* yuvconstants, @@ -543,7 +578,9 @@ void I400ToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_J400TOARGBROW_RVV void J400ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, int width) { size_t w = (size_t)width; size_t vl = __riscv_vsetvl_e8m2(w); @@ -558,7 +595,9 @@ void J400ToARGBRow_RVV(const uint8_t* src_y, uint8_t* dst_argb, int width) { vl = __riscv_vsetvl_e8m2(w); } while (w > 0); } +#endif +#ifdef HAS_COPYROW_RVV void CopyRow_RVV(const uint8_t* src, uint8_t* dst, int width) { size_t w = (size_t)width; do { @@ -570,7 +609,9 @@ void CopyRow_RVV(const uint8_t* src, uint8_t* dst, int width) { dst += vl; } while (w > 0); } +#endif +#ifdef HAS_NV12TOARGBROW_RVV void NV12ToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_uv, uint8_t* dst_argb, @@ -597,7 +638,9 @@ void NV12ToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_NV12TORGB24ROW_RVV void NV12ToRGB24Row_RVV(const uint8_t* src_y, const uint8_t* src_uv, uint8_t* dst_rgb24, @@ -623,7 +666,9 @@ void NV12ToRGB24Row_RVV(const uint8_t* src_y, dst_rgb24 += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_NV21TOARGBROW_RVV void NV21ToARGBRow_RVV(const uint8_t* src_y, const uint8_t* src_vu, uint8_t* dst_argb, @@ -650,7 +695,9 @@ void NV21ToARGBRow_RVV(const uint8_t* src_y, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_NV21TORGB24ROW_RVV void NV21ToRGB24Row_RVV(const uint8_t* src_y, const uint8_t* src_vu, uint8_t* dst_rgb24, @@ -676,8 +723,11 @@ void NV21ToRGB24Row_RVV(const uint8_t* src_y, dst_rgb24 += vl * 3; } while (w > 0); } +#endif // Bilinear filter [VLEN/8]x2 -> [VLEN/8]x1 + +#ifdef HAS_INTERPOLATEROW_RVV void InterpolateRow_RVV(uint8_t* dst_ptr, const uint8_t* src_ptr, ptrdiff_t src_stride, @@ -734,7 +784,9 @@ void InterpolateRow_RVV(uint8_t* dst_ptr, dst_ptr += vl; } while (dst_w > 0); } +#endif +#ifdef HAS_SPLITRGBROW_RVV void SplitRGBRow_RVV(const uint8_t* src_rgb, uint8_t* dst_r, uint8_t* dst_g, @@ -755,7 +807,9 @@ void SplitRGBRow_RVV(const uint8_t* src_rgb, src_rgb += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_MERGERGBROW_RVV void MergeRGBRow_RVV(const uint8_t* src_r, const uint8_t* src_g, const uint8_t* src_b, @@ -775,7 +829,9 @@ void MergeRGBRow_RVV(const uint8_t* src_r, dst_rgb += vl * 3; } while (w > 0); } +#endif +#ifdef HAS_SPLITARGBROW_RVV void SplitARGBRow_RVV(const uint8_t* src_argb, uint8_t* dst_r, uint8_t* dst_g, @@ -799,7 +855,9 @@ void SplitARGBRow_RVV(const uint8_t* src_argb, src_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_MERGEARGBROW_RVV void MergeARGBRow_RVV(const uint8_t* src_r, const uint8_t* src_g, const uint8_t* src_b, @@ -822,7 +880,9 @@ void MergeARGBRow_RVV(const uint8_t* src_r, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_SPLITXRGBROW_RVV void SplitXRGBRow_RVV(const uint8_t* src_argb, uint8_t* dst_r, uint8_t* dst_g, @@ -843,7 +903,9 @@ void SplitXRGBRow_RVV(const uint8_t* src_argb, src_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_MERGEXRGBROW_RVV void MergeXRGBRow_RVV(const uint8_t* src_r, const uint8_t* src_g, const uint8_t* src_b, @@ -866,7 +928,9 @@ void MergeXRGBRow_RVV(const uint8_t* src_r, vl = __riscv_vsetvl_e8m2(w); } while (w > 0); } +#endif +#ifdef HAS_SPLITUVROW_RVV void SplitUVRow_RVV(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, @@ -884,7 +948,9 @@ void SplitUVRow_RVV(const uint8_t* src_uv, src_uv += 2 * vl; } while (w > 0); } +#endif +#ifdef HAS_MERGEUVROW_RVV void MergeUVRow_RVV(const uint8_t* src_u, const uint8_t* src_v, uint8_t* dst_uv, @@ -902,6 +968,7 @@ void MergeUVRow_RVV(const uint8_t* src_u, dst_uv += 2 * vl; } while (w > 0); } +#endif struct RgbConstants { uint8_t kRGBToY[4]; @@ -934,7 +1001,8 @@ static const struct RgbConstants kRawI601Constants = {{66, 129, 25, 0}, 0x1080, 0}; -// ARGB expects first 3 values to contain RGB and 4th value is ignored. +// ARGB expects first 3 values to contain RGB and 4th value is ignored +#ifdef HAS_ARGBTOYMATRIXROW_RVV void ARGBToYMatrixRow_RVV(const uint8_t* src_argb, uint8_t* dst_y, int width, @@ -964,24 +1032,34 @@ void ARGBToYMatrixRow_RVV(const uint8_t* src_argb, dst_y += vl; } while (w > 0); } +#endif +#ifdef HAS_ARGBTOYROW_RVV void ARGBToYRow_RVV(const uint8_t* src_argb, uint8_t* dst_y, int width) { ARGBToYMatrixRow_RVV(src_argb, dst_y, width, &kRgb24I601Constants); } +#endif +#ifdef HAS_ARGBTOYJROW_RVV void ARGBToYJRow_RVV(const uint8_t* src_argb, uint8_t* dst_yj, int width) { ARGBToYMatrixRow_RVV(src_argb, dst_yj, width, &kRgb24JPEGConstants); } +#endif +#ifdef HAS_ABGRTOYROW_RVV void ABGRToYRow_RVV(const uint8_t* src_abgr, uint8_t* dst_y, int width) { ARGBToYMatrixRow_RVV(src_abgr, dst_y, width, &kRawI601Constants); } +#endif +#ifdef HAS_ABGRTOYJROW_RVV void ABGRToYJRow_RVV(const uint8_t* src_abgr, uint8_t* dst_yj, int width) { ARGBToYMatrixRow_RVV(src_abgr, dst_yj, width, &kRawJPEGConstants); } +#endif // RGBA expects first value to be A and ignored, then 3 values to contain RGB. +#ifdef HAS_RGBATOYMATRIXROW_RVV void RGBAToYMatrixRow_RVV(const uint8_t* src_rgba, uint8_t* dst_y, int width, @@ -1011,19 +1089,27 @@ void RGBAToYMatrixRow_RVV(const uint8_t* src_rgba, dst_y += vl; } while (w > 0); } +#endif +#ifdef HAS_RGBATOYROW_RVV void RGBAToYRow_RVV(const uint8_t* src_rgba, uint8_t* dst_y, int width) { RGBAToYMatrixRow_RVV(src_rgba, dst_y, width, &kRgb24I601Constants); } +#endif +#ifdef HAS_RGBATOYJROW_RVV void RGBAToYJRow_RVV(const uint8_t* src_rgba, uint8_t* dst_yj, int width) { RGBAToYMatrixRow_RVV(src_rgba, dst_yj, width, &kRgb24JPEGConstants); } +#endif +#ifdef HAS_BGRATOYROW_RVV void BGRAToYRow_RVV(const uint8_t* src_bgra, uint8_t* dst_y, int width) { RGBAToYMatrixRow_RVV(src_bgra, dst_y, width, &kRawI601Constants); } +#endif +#ifdef HAS_RGBTOYMATRIXROW_RVV void RGBToYMatrixRow_RVV(const uint8_t* src_rgb, uint8_t* dst_y, int width, @@ -1053,26 +1139,36 @@ void RGBToYMatrixRow_RVV(const uint8_t* src_rgb, dst_y += vl; } while (w > 0); } +#endif +#ifdef HAS_RGB24TOYJROW_RVV void RGB24ToYJRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) { RGBToYMatrixRow_RVV(src_rgb24, dst_yj, width, &kRgb24JPEGConstants); } +#endif +#ifdef HAS_RAWTOYJROW_RVV void RAWToYJRow_RVV(const uint8_t* src_raw, uint8_t* dst_yj, int width) { RGBToYMatrixRow_RVV(src_raw, dst_yj, width, &kRawJPEGConstants); } +#endif +#ifdef HAS_RGB24TOYROW_RVV void RGB24ToYRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_y, int width) { RGBToYMatrixRow_RVV(src_rgb24, dst_y, width, &kRgb24I601Constants); } +#endif +#ifdef HAS_RAWTOYROW_RVV void RAWToYRow_RVV(const uint8_t* src_raw, uint8_t* dst_y, int width) { RGBToYMatrixRow_RVV(src_raw, dst_y, width, &kRawI601Constants); } +#endif // Blend src_argb over src_argb1 and store to dst_argb. // dst_argb may be src_argb or src_argb1. // src_argb: RGB values have already been pre-multiplied by the a. +#ifdef HAS_ARGBBLENDROW_RVV void ARGBBlendRow_RVV(const uint8_t* src_argb, const uint8_t* src_argb1, uint8_t* dst_argb, @@ -1113,7 +1209,9 @@ void ARGBBlendRow_RVV(const uint8_t* src_argb, dst_argb += 4 * vl; } while (w > 0); } +#endif +#ifdef HAS_BLENDPLANEROW_RVV void BlendPlaneRow_RVV(const uint8_t* src0, const uint8_t* src1, const uint8_t* alpha, @@ -1144,8 +1242,10 @@ void BlendPlaneRow_RVV(const uint8_t* src0, dst += vl; } while (w > 0); } +#endif // Attenuate: (f * a + 255) >> 8 +#ifdef HAS_ARGBATTENUATEROW_RVV void ARGBAttenuateRow_RVV(const uint8_t* src_argb, uint8_t* dst_argb, int width) { @@ -1173,7 +1273,9 @@ void ARGBAttenuateRow_RVV(const uint8_t* src_argb, dst_argb += vl * 4; } while (w > 0); } +#endif +#ifdef HAS_ARGBEXTRACTALPHAROW_RVV void ARGBExtractAlphaRow_RVV(const uint8_t* src_argb, uint8_t* dst_a, int width) { @@ -1188,7 +1290,9 @@ void ARGBExtractAlphaRow_RVV(const uint8_t* src_argb, dst_a += vl; } while (w > 0); } +#endif +#ifdef HAS_ARGBCOPYYTOALPHAROW_RVV void ARGBCopyYToAlphaRow_RVV(const uint8_t* src, uint8_t* dst, int width) { size_t w = (size_t)width; const ptrdiff_t dst_stride = 4; @@ -1202,6 +1306,7 @@ void ARGBCopyYToAlphaRow_RVV(const uint8_t* src, uint8_t* dst, int width) { dst += vl * dst_stride; } while (w > 0); } +#endif #ifdef __cplusplus } // extern "C" -- cgit v1.2.3 From ec2e9ca0007df3ac1caae5c6c1fdddcbbe07a842 Mon Sep 17 00:00:00 2001 From: Bruce Lai Date: Fri, 18 Aug 2023 01:50:49 -0700 Subject: [RVV] Support AR64ToAB64 and RGBA-family color conversions Add scalar code for AR64ToAB64, ARGBToRGBA, ARGBToBGRA, ARGBToABGR, RGBAToARGB, BGRAToARGB, and ABGRToARGB. They are originally implemented by ARGBShffle. This CL independetly implements them, and only enables for risc-v now. This CL also add RVV implementation for `RGBA-family <-> RGBA-family` color conversions. * Run on SiFive internal FPGA(VLEN=128): Test Case Speedup AR64ToAB64_Opt x4.6 ARGBToRGBA_Opt x6 ARGBToBGRA_Opt x6 ARGBToABGR_Opt x6 RGBAToARGB_Opt x6 Change-Id: Ie0630901046084aa259699fcdeccc64170d7103f Signed-off-by: Bruce Lai Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4797451 Reviewed-by: Frank Barchard --- source/row_rvv.cc | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'source/row_rvv.cc') diff --git a/source/row_rvv.cc b/source/row_rvv.cc index c875be2f..0bf2bef6 100644 --- a/source/row_rvv.cc +++ b/source/row_rvv.cc @@ -200,6 +200,23 @@ void AR64ToARGBRow_RVV(const uint16_t* src_ar64, uint8_t* dst_argb, int width) { } #endif +#ifdef HAS_AR64TOAB64ROW_RVV +void AR64ToAB64Row_RVV(const uint16_t* src_ar64, + uint16_t* dst_ab64, + int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e16m2(w); + vuint16m2_t v_b, v_g, v_r, v_a; + __riscv_vlseg4e16_v_u16m2(&v_b, &v_g, &v_r, &v_a, src_ar64, vl); + __riscv_vsseg4e16_v_u16m2(dst_ab64, v_r, v_g, v_b, v_a, vl); + w -= vl; + src_ar64 += vl * 4; + dst_ab64 += vl * 4; + } while (w > 0); +} +#endif + #ifdef HAS_AB64TOARGBROW_RVV void AB64ToARGBRow_RVV(const uint16_t* src_ab64, uint8_t* dst_argb, int width) { size_t avl = (size_t)width; @@ -301,6 +318,66 @@ void ARGBToRGB24Row_RVV(const uint8_t* src_argb, } #endif +#ifdef HAS_ARGBTOABGRROW_RVV +void ARGBToABGRRow_RVV(const uint8_t* src_argb, uint8_t* dst_abgr, int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a, v_r, v_g, v_b; + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vsseg4e8_v_u8m2(dst_abgr, v_r, v_g, v_b, v_a, vl); + w -= vl; + src_argb += vl * 4; + dst_abgr += vl * 4; + } while (w > 0); +} +#endif + +#ifdef HAS_ARGBTOBGRAROW_RVV +void ARGBToBGRARow_RVV(const uint8_t* src_argb, uint8_t* dst_bgra, int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a, v_r, v_g, v_b; + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vsseg4e8_v_u8m2(dst_bgra, v_a, v_r, v_g, v_b, vl); + w -= vl; + src_argb += vl * 4; + dst_bgra += vl * 4; + } while (w > 0); +} +#endif + +#ifdef HAS_ARGBTORGBAROW_RVV +void ARGBToRGBARow_RVV(const uint8_t* src_argb, uint8_t* dst_rgba, int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a, v_r, v_g, v_b; + __riscv_vlseg4e8_v_u8m2(&v_b, &v_g, &v_r, &v_a, src_argb, vl); + __riscv_vsseg4e8_v_u8m2(dst_rgba, v_a, v_b, v_g, v_r, vl); + w -= vl; + src_argb += vl * 4; + dst_rgba += vl * 4; + } while (w > 0); +} +#endif + +#ifdef HAS_RGBATOARGBROW_RVV +void RGBAToARGBRow_RVV(const uint8_t* src_rgba, uint8_t* dst_argb, int width) { + size_t w = (size_t)width; + do { + size_t vl = __riscv_vsetvl_e8m2(w); + vuint8m2_t v_a, v_r, v_g, v_b; + __riscv_vlseg4e8_v_u8m2(&v_a, &v_b, &v_g, &v_r, src_rgba, vl); + __riscv_vsseg4e8_v_u8m2(dst_argb, v_b, v_g, v_r, v_a, vl); + w -= vl; + src_rgba += vl * 4; + dst_argb += vl * 4; + } while (w > 0); +} +#endif + #ifdef HAS_RGB24TOARGBROW_RVV void RGB24ToARGBRow_RVV(const uint8_t* src_rgb24, uint8_t* dst_argb, -- cgit v1.2.3