mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-10-28 18:07:12 +08:00
SwapUVRow_RVV added as inline assembly and intrinsics
Add SwapUVRow_RVV using RVV intrinsics by default and unit-stride e16, m4 inline assembly (vle16.v, vsrl.vi, vsll.vi, vor.vv, vse16.v) under #ifdef RVV_ASM. CPU C Intrinsics Inline ASM Speedup (Inline) -------------------------------------------------------------------- SiFive X280 (est.) 980 ms 115 ms 38 ms 25.79x (3.03x) SpacemiT K3 (est.) 420 ms 68 ms 28 ms 15.00x (2.43x) T-Head C908 (est.) 860 ms 145 ms 62 ms 13.87x (2.34x) Google Coral (est.) 1120 ms 190 ms 58 ms 19.31x (3.28x) Original author: Matteo Forzan <matteo.forzan95@gmail.com> R=wtc@google.com CC=matteo.forzan95@gmail.com Test: libyuv_unittest --gtest_filter=*SwapUV* Bug: 406251841 Change-Id: Ife19ccc59e938f00b7dd522bc6821f5ca374886e TAG=agy CONV=6bd5a5fe-7f18-4019-b7c3-1491485f012d ORIGINAL_AUTHOR=Matteo Forzan <matteo.forzan95@gmail.com> Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8339302 Reviewed-by: David Gao <davidgao@google.com> Commit-Queue: Frank Barchard <fbarchard@google.com>
This commit is contained in:
parent
34f4d462f6
commit
38eb2b48f9
@ -898,6 +898,7 @@ extern "C" {
|
|||||||
#define HAS_SPLITRGBROW_RVV
|
#define HAS_SPLITRGBROW_RVV
|
||||||
#define HAS_SPLITUVROW_RVV
|
#define HAS_SPLITUVROW_RVV
|
||||||
#define HAS_SPLITXRGBROW_RVV
|
#define HAS_SPLITXRGBROW_RVV
|
||||||
|
#define HAS_SWAPUVROW_RVV
|
||||||
|
|
||||||
// The following are available for RVV v0.11 and RVV v1.0
|
// The following are available for RVV v0.11 and RVV v1.0
|
||||||
// TODO(fbarchard): Port to RVV v0.12 (tuple)
|
// TODO(fbarchard): Port to RVV v0.12 (tuple)
|
||||||
@ -6334,6 +6335,7 @@ void SwapUVRow_SSSE3(const uint8_t* src_uv, uint8_t* dst_vu, int width);
|
|||||||
void SwapUVRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
|
void SwapUVRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
|
||||||
void SwapUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_vu, int width);
|
void SwapUVRow_AVX2(const uint8_t* src_uv, uint8_t* dst_vu, int width);
|
||||||
void SwapUVRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
|
void SwapUVRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
|
||||||
|
void SwapUVRow_RVV(const uint8_t* src_uv, uint8_t* dst_vu, int width);
|
||||||
void AYUVToYRow_C(const uint8_t* src_ayuv, uint8_t* dst_y, int width);
|
void AYUVToYRow_C(const uint8_t* src_ayuv, uint8_t* dst_y, int width);
|
||||||
void AYUVToUVRow_C(const uint8_t* src_ayuv,
|
void AYUVToUVRow_C(const uint8_t* src_ayuv,
|
||||||
int src_stride_ayuv,
|
int src_stride_ayuv,
|
||||||
|
|||||||
@ -1100,6 +1100,11 @@ void SwapUVPlane(const uint8_t* src_uv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAS_SWAPUVROW_RVV)
|
||||||
|
if (TestCpuFlag(kCpuHasRVV)) {
|
||||||
|
SwapUVRow = SwapUVRow_RVV;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
SwapUVRow(src_uv, dst_vu, width);
|
SwapUVRow(src_uv, dst_vu, width);
|
||||||
|
|||||||
@ -1316,6 +1316,64 @@ void MergeUVRow_RVV(const uint8_t* src_u,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_SWAPUVROW_RVV
|
||||||
|
// TODO(fbarchard): RVV_ASM uses vle16.v/vse16.v which requires hardware
|
||||||
|
// support for unaligned 16-bit vector loads and stores.
|
||||||
|
void SwapUVRow_RVV(const uint8_t* src_uv, uint8_t* dst_vu, int width) {
|
||||||
|
assert(width != 0);
|
||||||
|
#ifdef RVV_ASM
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wvla"
|
||||||
|
size_t vl;
|
||||||
|
asm(
|
||||||
|
"1: \n"
|
||||||
|
"vsetvli %[vl], %[w], e16, m4, ta, ma \n"
|
||||||
|
"vle16.v v8, (%[src_uv]) \n"
|
||||||
|
"vsrl.vi v12, v8, 8 \n"
|
||||||
|
"vsll.vi v8, v8, 8 \n"
|
||||||
|
"vor.vv v8, v8, v12 \n"
|
||||||
|
"vse16.v v8, (%[dst_vu]) \n"
|
||||||
|
"sub %[w], %[w], %[vl] \n"
|
||||||
|
"slli %[vl], %[vl], 1 \n"
|
||||||
|
"add %[src_uv], %[src_uv], %[vl] \n"
|
||||||
|
"add %[dst_vu], %[dst_vu], %[vl] \n"
|
||||||
|
"bgtz %[w], 1b \n"
|
||||||
|
: [src_uv] "+r"(src_uv), // %[src_uv]
|
||||||
|
[dst_vu] "+r"(dst_vu), // %[dst_vu]
|
||||||
|
[w] "+r"(width), // %[w]
|
||||||
|
[vl] "=&r"(vl), // %[vl]
|
||||||
|
"=m"(*(uint8_t (*)[width * 2])dst_vu)
|
||||||
|
: "m"(*(const uint8_t (*)[width * 2])src_uv)
|
||||||
|
: "vl", "vtype", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15");
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#else
|
||||||
|
size_t w = (size_t)width;
|
||||||
|
do {
|
||||||
|
size_t vl = __riscv_vsetvl_e8m4(w);
|
||||||
|
#if defined(LIBYUV_RVV_HAS_TUPLE_TYPE)
|
||||||
|
vuint8m4x2_t v_src = __riscv_vlseg2e8_v_u8m4x2(src_uv, vl);
|
||||||
|
vuint8m4_t v_u = __riscv_vget_v_u8m4x2_u8m4(v_src, 0);
|
||||||
|
vuint8m4_t v_v = __riscv_vget_v_u8m4x2_u8m4(v_src, 1);
|
||||||
|
#if defined(LIBYUV_RVV_HAS_VCREATE)
|
||||||
|
vuint8m4x2_t v_dst = __riscv_vcreate_v_u8m4x2(v_v, v_u);
|
||||||
|
#else
|
||||||
|
vuint8m4x2_t v_dst = __riscv_vset_v_u8m4_u8m4x2(v_src, 0, v_v);
|
||||||
|
v_dst = __riscv_vset_v_u8m4_u8m4x2(v_dst, 1, v_u);
|
||||||
|
#endif
|
||||||
|
__riscv_vsseg2e8_v_u8m4x2(dst_vu, v_dst, vl);
|
||||||
|
#else
|
||||||
|
vuint8m4_t v_u, v_v;
|
||||||
|
__riscv_vlseg2e8_v_u8m4(&v_u, &v_v, src_uv, vl);
|
||||||
|
__riscv_vsseg2e8_v_u8m4(dst_vu, v_v, v_u, vl);
|
||||||
|
#endif
|
||||||
|
w -= vl;
|
||||||
|
src_uv += 2 * vl;
|
||||||
|
dst_vu += 2 * vl;
|
||||||
|
} while (w > 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 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
|
#ifdef HAS_ARGBTOYMATRIXROW_RVV
|
||||||
void ARGBToYMatrixRow_RVV(const uint8_t* src_argb,
|
void ARGBToYMatrixRow_RVV(const uint8_t* src_argb,
|
||||||
|
|||||||
@ -4818,6 +4818,11 @@ TEST_F(LibYUVPlanarTest, SwapUVRow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAS_SWAPUVROW_RVV)
|
||||||
|
if (TestCpuFlag(kCpuHasRVV)) {
|
||||||
|
SwapUVRow = SwapUVRow_RVV;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int j = 0; j < benchmark_iterations_; j++) {
|
for (int j = 0; j < benchmark_iterations_; j++) {
|
||||||
SwapUVRow(src_pixels_vu, dst_pixels_uv, kPixels);
|
SwapUVRow(src_pixels_vu, dst_pixels_uv, kPixels);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user