| /* |
| * Copyright (c) 2026, Alliance for Open Media. All rights reserved. |
| * |
| * This source code is subject to the terms of the BSD 2 Clause License and |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| * was not distributed with this source code in the LICENSE file, you can |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| * Media Patent License 1.0 was not distributed with this source code in the |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| */ |
| |
| #ifndef AOM_AV1_COMMON_RISCV_HIGHBD_COMPOUND_CONVOLVE_RVV_H_ |
| #define AOM_AV1_COMMON_RISCV_HIGHBD_COMPOUND_CONVOLVE_RVV_H_ |
| |
| #include <riscv_vector.h> |
| #include <assert.h> |
| |
| #include "config/aom_config.h" |
| #include "config/av1_rtcd.h" |
| #include "aom_dsp/riscv/mem_rvv.h" |
| #include "aom_ports/mem.h" |
| |
| #define ROUND_SHIFT 2 * FILTER_BITS - ROUND0_BITS - COMPOUND_ROUND1_BITS |
| |
| static inline void highbd_comp_avg_rvv(const uint16_t *src_ptr, int src_stride, |
| uint16_t *dst_ptr, int dst_stride, int w, |
| int h, ConvolveParams *conv_params, |
| const int bd, const int shift_bits, |
| const int offset_bits) { |
| const uint16_t offset = (1 << (offset_bits - COMPOUND_ROUND1_BITS)) + |
| (1 << (offset_bits - COMPOUND_ROUND1_BITS - 1)); |
| const uint16_t max_val = (1 << bd) - 1; |
| const int32_t round_shift_val = 1 << (shift_bits - 1); |
| |
| CONV_BUF_TYPE *ref_ptr = conv_params->dst; |
| const int ref_stride = conv_params->dst_stride; |
| const size_t vl = __riscv_vsetvl_e16m1(w); |
| |
| if (w == 4) { |
| do { |
| vuint16m1_t src = __riscv_vle16_v_u16m1(src_ptr, vl); |
| vuint16m1_t ref = __riscv_vle16_v_u16m1(ref_ptr, vl); |
| |
| #if __riscv_v_intrinsic >= 12000 |
| vuint16m1_t avg = __riscv_vaaddu_vv_u16m1(src, ref, __RISCV_VXRM_RDN, vl); |
| #else |
| vuint16m1_t avg = |
| __riscv_vnsrl_wx_u16m1(__riscv_vwaddu_vv_u32m2(src, ref, vl), 1, vl); |
| #endif |
| vint32m2_t diff = __riscv_vreinterpret_v_u32m2_i32m2( |
| __riscv_vwsubu_vx_u32m2(avg, offset, vl)); |
| diff = __riscv_vadd_vx_i32m2(diff, round_shift_val, vl); |
| vint16m1_t d0 = __riscv_vnsra_wx_i16m1(diff, shift_bits, vl); |
| vuint16m1_t d0_u16 = |
| __riscv_vreinterpret_v_i16m1_u16m1(__riscv_vmax_vx_i16m1(d0, 0, vl)); |
| d0_u16 = __riscv_vminu_vx_u16m1(d0_u16, max_val, vl); |
| |
| __riscv_vse16_v_u16m1(dst_ptr, d0_u16, vl); |
| |
| src_ptr += src_stride; |
| ref_ptr += ref_stride; |
| dst_ptr += dst_stride; |
| } while (--h != 0); |
| } else { |
| do { |
| int width = w; |
| const uint16_t *src_line = src_ptr; |
| const uint16_t *ref_line = (const uint16_t *)ref_ptr; |
| uint16_t *dst_line = dst_ptr; |
| |
| while (width > 0) { |
| vuint16m1_t s = __riscv_vle16_v_u16m1(src_line, vl); |
| vuint16m1_t r = __riscv_vle16_v_u16m1(ref_line, vl); |
| |
| #if __riscv_v_intrinsic >= 12000 |
| vuint16m1_t avg = __riscv_vaaddu_vv_u16m1(s, r, __RISCV_VXRM_RDN, vl); |
| #else |
| vuint16m1_t avg = |
| __riscv_vnsrl_wx_u16m1(__riscv_vwaddu_vv_u32m2(s, r, vl), 1, vl); |
| #endif |
| vint32m2_t diff = __riscv_vreinterpret_v_u32m2_i32m2( |
| __riscv_vwsubu_vx_u32m2(avg, offset, vl)); |
| diff = __riscv_vadd_vx_i32m2(diff, round_shift_val, vl); |
| vint16m1_t d0 = __riscv_vnsra_wx_i16m1(diff, shift_bits, vl); |
| vuint16m1_t d0_u16 = __riscv_vreinterpret_v_i16m1_u16m1( |
| __riscv_vmax_vx_i16m1(d0, 0, vl)); |
| d0_u16 = __riscv_vminu_vx_u16m1(d0_u16, max_val, vl); |
| |
| __riscv_vse16_v_u16m1(dst_line, d0_u16, vl); |
| |
| src_line += vl; |
| ref_line += vl; |
| dst_line += vl; |
| width -= vl; |
| } |
| |
| src_ptr += src_stride; |
| ref_ptr += ref_stride; |
| dst_ptr += dst_stride; |
| } while (--h != 0); |
| } |
| } |
| |
| static inline void highbd_dist_wtd_comp_avg_rvv( |
| const uint16_t *src_ptr, int src_stride, uint16_t *dst_ptr, int dst_stride, |
| int w, int h, ConvolveParams *conv_params, const int bd, |
| const int shift_bits, const int offset_bits) { |
| const int offset = (1 << (offset_bits - COMPOUND_ROUND1_BITS)) + |
| (1 << (offset_bits - COMPOUND_ROUND1_BITS - 1)); |
| const uint16_t max_val = (1 << bd) - 1; |
| const uint16_t fwd = conv_params->fwd_offset; |
| const uint16_t bck = conv_params->bck_offset; |
| |
| CONV_BUF_TYPE *ref_ptr = conv_params->dst; |
| const int ref_stride = conv_params->dst_stride; |
| |
| const size_t vl = __riscv_vsetvl_e16m1(w); |
| vuint32m2_t offset_vec = __riscv_vmv_v_x_u32m2((uint32_t)offset, vl); |
| if (w == 4) { |
| do { |
| vuint16m1_t src = __riscv_vle16_v_u16m1(src_ptr, vl); |
| vuint16m1_t ref = __riscv_vle16_v_u16m1(ref_ptr, vl); |
| |
| vuint32m2_t wtd = __riscv_vwmulu_vx_u32m2(ref, fwd, vl); |
| wtd = __riscv_vwmaccu_vx_u32m2(wtd, bck, src, vl); |
| wtd = __riscv_vsrl_vx_u32m2(wtd, DIST_PRECISION_BITS, vl); |
| |
| vint32m2_t diff = __riscv_vreinterpret_v_u32m2_i32m2( |
| __riscv_vsub_vv_u32m2(wtd, offset_vec, vl)); |
| |
| vuint32m2_t d0 = __riscv_vreinterpret_v_i32m2_u32m2( |
| __riscv_vmax_vx_i32m2(diff, 0, vl)); |
| #if __riscv_v_intrinsic >= 12000 |
| vuint16m1_t d0_u16 = |
| __riscv_vnclipu_wx_u16m1(d0, shift_bits, __RISCV_VXRM_RNU, vl); |
| #else |
| vuint16m1_t d0_u16 = __riscv_vnclipu_wx_u16m1(d0, shift_bits, vl); |
| #endif |
| d0_u16 = __riscv_vminu_vx_u16m1(d0_u16, max_val, vl); |
| |
| __riscv_vse16_v_u16m1(dst_ptr, d0_u16, vl); |
| |
| src_ptr += src_stride; |
| dst_ptr += dst_stride; |
| ref_ptr += ref_stride; |
| } while (--h != 0); |
| } else { |
| do { |
| int width = w; |
| const uint16_t *src_line = src_ptr; |
| const uint16_t *ref_line = (const uint16_t *)ref_ptr; |
| uint16_t *dst_line = dst_ptr; |
| |
| while (width > 0) { |
| vuint16m1_t s = __riscv_vle16_v_u16m1(src_line, vl); |
| vuint16m1_t r = __riscv_vle16_v_u16m1(ref_line, vl); |
| |
| vuint32m2_t wtd = __riscv_vwmulu_vx_u32m2(r, fwd, vl); |
| wtd = __riscv_vwmaccu_vx_u32m2(wtd, bck, s, vl); |
| wtd = __riscv_vsrl_vx_u32m2(wtd, DIST_PRECISION_BITS, vl); |
| |
| vint32m2_t diff = __riscv_vreinterpret_v_u32m2_i32m2( |
| __riscv_vsub_vv_u32m2(wtd, offset_vec, vl)); |
| |
| vuint32m2_t d0 = __riscv_vreinterpret_v_i32m2_u32m2( |
| __riscv_vmax_vx_i32m2(diff, 0, vl)); |
| #if __riscv_v_intrinsic >= 12000 |
| vuint16m1_t d0_u16 = |
| __riscv_vnclipu_wx_u16m1(d0, shift_bits, __RISCV_VXRM_RNU, vl); |
| #else |
| vuint16m1_t d0_u16 = __riscv_vnclipu_wx_u16m1(d0, shift_bits, vl); |
| #endif |
| d0_u16 = __riscv_vminu_vx_u16m1(d0_u16, max_val, vl); |
| |
| __riscv_vse16_v_u16m1(dst_line, d0_u16, vl); |
| |
| src_line += vl; |
| ref_line += vl; |
| dst_line += vl; |
| width -= vl; |
| } |
| |
| src_ptr += src_stride; |
| dst_ptr += dst_stride; |
| ref_ptr += ref_stride; |
| } while (--h != 0); |
| } |
| } |
| |
| #endif // AOM_AV1_COMMON_RISCV_HIGHBD_COMPOUND_CONVOLVE_RVV_H_ |