// partial A is a 16-bit vector of the form: // [x8 x7 x6 x5 x4 x3 x2 x1] and partial B has the form: // [0 y1 y2 y3 y4 y5 y6 y7]. // This function computes (x1^2+y1^2)*C1 + (x2^2+y2^2)*C2 + ... // (x7^2+y2^7)*C7 + (x8^2+0^2)*C8 where the C1..C8 constants are in const1 // and const2. static inline vuint32m1_t fold_mul_and_sum_rvv(vint16m1_t partiala,
vint16m1_t partialb,
vuint32m1_t const1,
vuint32m1_t const2) { // Square and add the corresponding x and y values.
vint32m2_t cost = __riscv_vwmul_vv_i32m2(partiala, partiala, 8);
cost = __riscv_vwmacc_vv_i32m2(cost, partialb, partialb, 8);
// This function computes the cost along directions 4, 5, 6, 7. (4 is diagonal // down-right, 6 is vertical). // // For each direction the lines are shifted so that we can perform a // basic sum on each vector element. For example, direction 5 is "south by // southeast", so we need to add the pixels along each line i below: // // 0 1 2 3 4 5 6 7 // 0 1 2 3 4 5 6 7 // 8 0 1 2 3 4 5 6 // 8 0 1 2 3 4 5 6 // 9 8 0 1 2 3 4 5 // 9 8 0 1 2 3 4 5 // 10 9 8 0 1 2 3 4 // 10 9 8 0 1 2 3 4 // // For this to fit nicely in vectors, the lines need to be shifted like so: // 0 1 2 3 4 5 6 7 // 0 1 2 3 4 5 6 7 // 8 0 1 2 3 4 5 6 // 8 0 1 2 3 4 5 6 // 9 8 0 1 2 3 4 5 // 9 8 0 1 2 3 4 5 // 10 9 8 0 1 2 3 4 // 10 9 8 0 1 2 3 4 // // In this configuration we can now perform SIMD additions to get the cost // along direction 5. Since this won't fit into a single 128-bit vector, we use // two of them to compute each half of the new configuration, and pad the empty // spaces with zeros. Similar shifting is done for other directions, except // direction 6 which is straightforward as it's the vertical direction. static vuint32m1_t compute_vert_directions_rvv(
vint16m1_t lines_0, vint16m1_t lines_1, vint16m1_t lines_2,
vint16m1_t lines_3, vint16m1_t lines_4, vint16m1_t lines_5,
vint16m1_t lines_6, vint16m1_t lines_7, uint32_t cost[4], size_t vl) {
size_t VL_SLIDE_DOWN = __riscv_vsetvl_e16m1(16);
vint16m1_t vec_zero_i16m1 = __riscv_vmv_v_x_i16m1(0, vl);
// Special case for direction 2 as it's just a sum along each line.
vint32m1_t partial2a =
horizontal_add_4d_s16x8(lines_0, lines_1, lines_2, lines_3);
vint32m1_t partial2b =
horizontal_add_4d_s16x8(lines_4, lines_5, lines_6, lines_7);
vuint32m1_t partial2a_u32 = __riscv_vreinterpret_v_i32m1_u32m1(
__riscv_vmul_vv_i32m1(partial2a, partial2a, 4));
vuint32m1_t partial2b_u32 = __riscv_vreinterpret_v_i32m1_u32m1(
__riscv_vmul_vv_i32m1(partial2b, partial2b, 4));
// Find max cost as well as its index to get best_dir. // The max cost needs to be propagated in the whole vector to find its // position in the original cost vectors cost03 and cost47.
vuint32m1_t vec_scalar_u32m1 = __riscv_vmv_s_x_u32m1(0, 1);
vuint32m1_t cost07 = __riscv_vmaxu_vv_u32m1(cost03, cost47, 4);
uint32_t best_cost = __riscv_vmv_x_s_u32m1_u32(
__riscv_vredmaxu_vs_u32m1_u32m1(cost07, vec_scalar_u32m1, 4));
vbool32_t mask_cost = __riscv_vmseq_vx_u32m1_b32(cost03, best_cost, 4);
long best_dir = __riscv_vfirst_m_b32(mask_cost, 4);
if (best_dir == -1) {
mask_cost = __riscv_vmseq_vx_u32m1_b32(cost47, best_cost, 4);
best_dir = __riscv_vfirst_m_b32(mask_cost, 4);
best_dir += 4;
}
// Difference between the optimal variance and the variance along the // orthogonal direction. Again, the sum(x^2) terms cancel out.
*var = best_cost - cost[(best_dir + 4) & 7];
// We'd normally divide by 840, but dividing by 1024 is close enough // for what we're going to do with this.
*var >>= 10; return (int)best_dir;
}
void cdef_copy_rect8_8bit_to_16bit_rvv(uint16_t *dst, int dstride, const uint8_t *src, int sstride,
int width, int height) { do {
int w = 0;
size_t num_cols = width; while (num_cols > 0) {
size_t vl = __riscv_vsetvl_e8mf2(num_cols);
vuint8mf2_t u8_src = __riscv_vle8_v_u8mf2(src + w, vl);
vuint16m1_t u16_src = __riscv_vwcvtu_x_x_v_u16m1(u8_src, vl);
__riscv_vse16_v_u16m1(dst + w, u16_src, vl);
w += vl;
num_cols -= vl;
}
src += sstride;
dst += dstride;
} while (--height != 0);
}
void cdef_copy_rect8_16bit_to_16bit_rvv(uint16_t *dst, int dstride, const uint16_t *src, int sstride,
int width, int height) { do {
int w = 0;
size_t num_cols = width; while (num_cols > 0) {
size_t vl = __riscv_vsetvl_e16m1(num_cols);
vuint16m1_t u16_src = __riscv_vle16_v_u16m1(src + w, vl);
__riscv_vse16_v_u16m1(dst + w, u16_src, vl);
w += vl;
num_cols -= vl;
}
src += sstride;
dst += dstride;
} while (--height != 0);
}
#define STORE16_UNCLAMPED \ do { \
BIAS; \
vuint16m1_t vdst = __riscv_vreinterpret_v_i16m1_u16m1(unclamped); \
STORE16; \
} while (0)
void cdef_filter_8_0_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) { const int po1 = cdef_directions[dir][0]; const int po2 = cdef_directions[dir][1]; const int s1o1 = cdef_directions[dir + 2][0]; const int s1o2 = cdef_directions[dir + 2][1]; const int s2o1 = cdef_directions[dir - 2][0]; const int s2o2 = cdef_directions[dir - 2][1];
MAKE_TAPS;
if (pri_strength) {
pri_damping = AOMMAX(0, pri_damping - get_msb(pri_strength));
}
if (sec_strength) {
sec_damping = AOMMAX(0, sec_damping - get_msb(sec_strength));
}
if (block_width == 8) {
uint8_t *dst8 = (uint8_t *)dest;
int h = block_height; const size_t vl = block_width; do {
LOAD_PIX(in);
SETUP_MINMAX;
void cdef_filter_8_1_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) {
(void)sec_strength;
(void)sec_damping;
const int po1 = cdef_directions[dir][0]; const int po2 = cdef_directions[dir][1];
MAKE_TAPS;
if (pri_strength) {
pri_damping = AOMMAX(0, pri_damping - get_msb(pri_strength));
}
if (block_width == 8) {
uint8_t *dst8 = (uint8_t *)dest;
int h = block_height; const size_t vl = block_width; do {
LOAD_PIX(in);
void cdef_filter_8_2_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) {
(void)pri_strength;
(void)pri_damping;
(void)coeff_shift;
const int s1o1 = cdef_directions[dir + 2][0]; const int s1o2 = cdef_directions[dir + 2][1]; const int s2o1 = cdef_directions[dir - 2][0]; const int s2o2 = cdef_directions[dir - 2][1];
if (sec_strength) {
sec_damping = AOMMAX(0, sec_damping - get_msb(sec_strength));
}
if (block_width == 8) {
uint8_t *dst8 = (uint8_t *)dest;
int h = block_height; const size_t vl = block_width; do {
LOAD_PIX(in);
void cdef_filter_8_3_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) {
(void)pri_strength;
(void)sec_strength;
(void)dir;
(void)pri_damping;
(void)sec_damping;
(void)coeff_shift;
if (block_width == 8) {
uint8_t *dst8 = (uint8_t *)dest;
int h = block_height; const size_t vl = block_width; do { const vuint16m1_t px = __riscv_vle16_v_u16m1(in, vl); const vuint8mf2_t vdst = __riscv_vncvt_x_x_w_u8mf2(px, vl);
__riscv_vse8_v_u8mf2(dst8, vdst, vl);
in += CDEF_BSTRIDE;
dst8 += dstride;
} while (--h != 0);
} else {
uint8_t *dst8 = (uint8_t *)dest;
int h = block_height; const size_t vl = block_width << 1; do { const vint16m1_t px =
load_strided_i16_4x2((int16_t *)in, CDEF_BSTRIDE, vl);
vuint8mf2_t vdst =
__riscv_vncvt_x_x_w_u8mf2(__riscv_vreinterpret_v_i16m1_u16m1(px), vl);
store_strided_u8_4x2(dst8, vdst, dstride, vl);
in += 2 * CDEF_BSTRIDE;
dst8 += 2 * dstride;
h -= 2;
} while (h != 0);
}
}
void cdef_filter_16_0_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) { const int po1 = cdef_directions[dir][0]; const int po2 = cdef_directions[dir][1]; const int s1o1 = cdef_directions[dir + 2][0]; const int s1o2 = cdef_directions[dir + 2][1]; const int s2o1 = cdef_directions[dir - 2][0]; const int s2o2 = cdef_directions[dir - 2][1];
MAKE_TAPS;
if (pri_strength) {
pri_damping = AOMMAX(0, pri_damping - get_msb(pri_strength));
}
if (sec_strength) {
sec_damping = AOMMAX(0, sec_damping - get_msb(sec_strength));
}
if (block_width == 8) {
uint16_t *dst16 = (uint16_t *)dest;
int h = block_height; const size_t vl = block_width; do {
LOAD_PIX(in);
SETUP_MINMAX;
void cdef_filter_16_1_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) {
(void)sec_strength;
(void)sec_damping;
const int po1 = cdef_directions[dir][0]; const int po2 = cdef_directions[dir][1];
MAKE_TAPS;
if (pri_strength) {
pri_damping = AOMMAX(0, pri_damping - get_msb(pri_strength));
}
if (block_width == 8) {
uint16_t *dst16 = (uint16_t *)dest;
int h = block_height; const size_t vl = block_width; do {
LOAD_PIX(in);
void cdef_filter_16_2_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) {
(void)pri_strength;
(void)pri_damping;
(void)coeff_shift;
const int s1o1 = cdef_directions[dir + 2][0]; const int s1o2 = cdef_directions[dir + 2][1]; const int s2o1 = cdef_directions[dir - 2][0]; const int s2o2 = cdef_directions[dir - 2][1];
if (sec_strength) {
sec_damping = AOMMAX(0, sec_damping - get_msb(sec_strength));
}
if (block_width == 8) {
uint16_t *dst16 = (uint16_t *)dest;
int h = block_height; const size_t vl = block_width; do {
LOAD_PIX(in);
void cdef_filter_16_3_rvv(void *dest, int dstride, const uint16_t *in,
int pri_strength, int sec_strength, int dir,
int pri_damping, int sec_damping, int coeff_shift,
int block_width, int block_height) {
(void)pri_strength;
(void)sec_strength;
(void)dir;
(void)pri_damping;
(void)sec_damping;
(void)coeff_shift;
if (block_width == 8) {
uint16_t *dst16 = (uint16_t *)dest;
int h = block_height; const size_t vl = block_width; do { const vuint16m1_t px = __riscv_vle16_v_u16m1(in, vl);
__riscv_vse16_v_u16m1(dst16, px, vl);
in += CDEF_BSTRIDE;
dst16 += dstride;
} while (--h != 0);
} else {
uint16_t *dst16 = (uint16_t *)dest;
int h = block_height; const size_t vl = block_width << 1; do { const vint16m1_t px =
load_strided_i16_4x2((int16_t *)in, CDEF_BSTRIDE, vl);
vuint16m1_t vdst = __riscv_vreinterpret_v_i16m1_u16m1(px);
store_strided_u16_4x2(dst16, vdst, dstride, vl);
in += 2 * CDEF_BSTRIDE;
dst16 += 2 * dstride;
h -= 2;
} while (h != 0);
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-08-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.