diff --git a/src/filmgrain_tmpl.c b/src/filmgrain_tmpl.c index 12e91dd6..352ed244 100644 --- a/src/filmgrain_tmpl.c +++ b/src/filmgrain_tmpl.c @@ -417,6 +417,8 @@ fguv_ss_fn(444, 0, 0); #include "src/arm/filmgrain.h" #elif ARCH_X86 #include "src/x86/filmgrain.h" +#elif ARCH_RISCV +#include "src/riscv/filmgrain.h" #endif #endif @@ -436,6 +438,8 @@ COLD void bitfn(dav1d_film_grain_dsp_init)(Dav1dFilmGrainDSPContext *const c) { film_grain_dsp_init_arm(c); #elif ARCH_X86 film_grain_dsp_init_x86(c); +#elif ARCH_RISCV + film_grain_dsp_init_riscv(c); #endif #endif } diff --git a/src/meson.build b/src/meson.build index 108b7623..61870b40 100644 --- a/src/meson.build +++ b/src/meson.build @@ -277,6 +277,7 @@ if is_asm_enabled if dav1d_bitdepths.contains('8') libdav1d_sources += files( 'riscv/64/cdef.S', + 'riscv/64/filmgrain.S', 'riscv/64/ipred.S', 'riscv/64/itx.S', 'riscv/64/mc.S', @@ -286,6 +287,7 @@ if is_asm_enabled if dav1d_bitdepths.contains('16') libdav1d_sources += files( 'riscv/64/cdef16.S', + 'riscv/64/filmgrain16.S', 'riscv/64/ipred16.S', 'riscv/64/mc16.S', ) diff --git a/src/riscv/64/filmgrain.S b/src/riscv/64/filmgrain.S new file mode 100644 index 00000000..24037f61 --- /dev/null +++ b/src/riscv/64/filmgrain.S @@ -0,0 +1,250 @@ +/* + * Copyright © 2026, VideoLAN and dav1d authors + * Copyright © 2026, Mohd Zaid + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/riscv/asm.S" +#include "src/riscv/asm-offsets.h" + +#define GRAIN_WIDTH 82 +#define GRAIN_HEIGHT 73 + +function generate_grain_y_8bpc_rvv, export=1, ext="v,zba,zbb" + lbu t1, FGD_GRAIN_SCALE_SHIFT(a1) + lla a2, dav1d_gaussian_sequence + lwu a5, FGD_SEED(a1) + + addi t1, t1, 4 + addi sp, sp, -256 + + csrwi vxrm, 0 + li t2, GRAIN_HEIGHT +0: + li t3, GRAIN_WIDTH +1: + vsetvli t0, t3, e16, m8, ta, ma + mv t6, t0 + mv a6, sp +2: + // get random number + + srliw t4, a5, 1 + xor t5, a5, t4 + srliw t4, a5, 3 + xor t5, t5, t4 + srliw t4, a5, 12 + xor t5, t5, t4 + andi t5, t5, 3 + + srliw a5, a5, 2 + slli t5, t5, 14 + or a5, a5, t5 + + // gaussian sequence [value] + + srliw t4, a5, 4 + andi t4, t4, 2047 + slli t4, t4, 1 + + srliw a7, a5, 5 + andi a7, a7, 2047 + slli a7, a7, 17 + or t4, t4, a7 + + // push data onto stack + + sw t4, 0(a6) + addi a6, a6, 4 + addi t6, t6, -2 + bnez t6, 2b + + // round2 and store + + vsetvli zero, t0, e16, m8, ta, ma + vle16.v v8, (sp) + vloxei16.v v16, (a2), v8 + + vsetvli zero, t0, e8, m4, ta, ma + vnclip.wx v4, v16, t1 + vse8.v v4, (a0) + + add a0, a0, t0 + sub t3, t3, t0 + bnez t3, 1b + + addi t2, t2, -1 + bnez t2, 0b + + addi sp, sp, 256 + + // AR FILTER + +3: + li t0, GRAIN_WIDTH * GRAIN_HEIGHT + sub a0, a0, t0 + + lb t1, FGD_AR_COEFF_LAG(a1) + beqz t1, 15f + + addi sp, sp, -512 + + lbu t2, FGD_AR_COEFF_SHIFT(a1) + addi t3, a1, FGD_AR_COEFFS_Y + + li t4, 3 + li a2, GRAIN_WIDTH + + // vector pre-sum (dy < 0 taps) + +4: + li a1, GRAIN_HEIGHT + bge t4, a1, 14f + + li a4, GRAIN_WIDTH - 6 + li t6, 3 + mv t0, sp + +5: + vsetvli a1, a4, e8, m2, ta, ma + vsetvli zero, zero, e32, m8, ta, ma + vmv.v.i v24, 0 + + sub a7, zero, t1 + mv a6, t3 + + add a3, t4, a7 + mul a3, a3, a2 + add a3, a3, a0 + add a3, a3, t6 + + vsetvli zero, zero, e16, m4, ta, ma + +6: + bge a7, zero, 9f + + sub a5, zero, t1 + add a3, a3, a5 + + // dx loop + sub a5, zero, t1 +7: + bgt a5, t1, 8f + + lb t5, 0(a6) + addi a6, a6, 1 + + vle8.v v16, (a3) + addi a3, a3, 1 + + vsext.vf2 v20, v16 + vwmacc.vx v24, t5, v20 + + addi a5, a5, 1 + j 7b + +8: + add a3, a3, a2 + sub a3, a3, t1 + addi a3, a3, -1 + + addi a7, a7, 1 + j 6b + +9: + vsetvli zero, a1, e32, m8, ta, ma + vse32.v v24, (t0) + + add t6, t6, a1 + slli a3, a1, 2 + add t0, t0, a3 + sub a4, a4, a1 + bnez a4, 5b + + // scalar horizontal pass (dx < 0, dy = 0) + + li a4, 3 + mv t0, sp + mul a3, t4, a2 + add a3, a3, a0 + +10: + li a1, GRAIN_WIDTH - 3 + bge a4, a1, 13f + + lw a5, 0(t0) + addi t0, t0, 4 + + mv a6, t3 + li a1, 2 + mul a1, a1, t1 + addi a1, a1, 1 + mul a1, a1, t1 + add a6, a6, a1 + + add a1, a3, a4 + sub a7, zero, t1 + +11: + bge a7, zero, 12f + + lb t5, 0(a6) + addi a6, a6, 1 + add t6, a1, a7 + lb t6, 0(t6) + mul t6, t6, t5 + add a5, a5, t6 + + addi a7, a7, 1 + j 11b + +12: + li a1, 1 + sll a1, a1, t2 + srai a1, a1, 1 + add a5, a5, a1 + sra a5, a5, t2 + + add a1, a3, a4 + lb t5, 0(a1) + add a5, a5, t5 + + li t5, -128 + max a5, a5, t5 + li t5, 127 + min a5, a5, t5 + + sb a5, 0(a1) + addi a4, a4, 1 + j 10b + +13: + addi t4, t4, 1 + j 4b + +14: + addi sp, sp, 512 +15: + ret +endfunc diff --git a/src/riscv/64/filmgrain16.S b/src/riscv/64/filmgrain16.S new file mode 100644 index 00000000..4fa218bd --- /dev/null +++ b/src/riscv/64/filmgrain16.S @@ -0,0 +1,266 @@ +/* + * Copyright © 2024, VideoLAN and dav1d authors + * Copyright © 2024, Mohd Zaid + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "src/riscv/asm.S" +#include "src/riscv/asm-offsets.h" + +#define GRAIN_WIDTH 82 +#define GRAIN_HEIGHT 73 + +function generate_grain_y_16bpc_rvv, export=1, ext="v,zba,zbb" + addi sp, sp, -32 + sd s0, 0(sp) + sd s1, 8(sp) + sd s2, 16(sp) + + // bitdepth scaling + clzw t0, a2 + li t1, 24 + sub t0, t1, t0 + + li t3, 128 + sll t3, t3, t0 + + lbu t1, FGD_GRAIN_SCALE_SHIFT(a1) + li t2, 4 + sub t2, t2, t0 + add t1, t1, t2 + + sub s1, zero, t3 + addi s2, t3, -1 + + lla a4, dav1d_gaussian_sequence + lwu a5, FGD_SEED(a1) + + addi sp, sp, -256 + + csrwi vxrm, 0 + li t2, GRAIN_HEIGHT +0: + li t3, GRAIN_WIDTH +1: + vsetvli t0, t3, e16, m8, ta, ma + mv t6, t0 + mv a6, sp +2: + srliw t4, a5, 1 + xor t5, a5, t4 + srliw t4, a5, 3 + xor t5, t5, t4 + srliw t4, a5, 12 + xor t5, t5, t4 + andi t5, t5, 3 + + srliw a5, a5, 2 + slli t5, t5, 14 + or a5, a5, t5 + + srliw t4, a5, 4 + andi t4, t4, 2047 + slli t4, t4, 1 + + srliw a7, a5, 5 + andi a7, a7, 2047 + slli a7, a7, 17 + or t4, t4, a7 + + sw t4, 0(a6) + addi a6, a6, 4 + addi t6, t6, -2 + bnez t6, 2b + + vsetvli zero, t0, e16, m8, ta, ma + vle16.v v8, (sp) + + vloxei16.v v16, (a4), v8 + + vssra.vx v8, v16, t1 + vse16.v v8, (a0) + + slli t4, t0, 1 + add a0, a0, t4 + sub t3, t3, t0 + bnez t3, 1b + + addi t2, t2, -1 + bnez t2, 0b + + addi sp, sp, 256 + + // AR FILTER + +3: + li t0, GRAIN_WIDTH * GRAIN_HEIGHT * 2 + sub a0, a0, t0 + + lb t0, FGD_AR_COEFF_LAG(a1) + beqz t0, 15f + + addi sp, sp, -512 + + lbu t2, FGD_AR_COEFF_SHIFT(a1) + addi t3, a1, FGD_AR_COEFFS_Y + + li t4, 3 + li a2, GRAIN_WIDTH + +4: + li a4, GRAIN_HEIGHT + bge t4, a4, 14f + + li a4, GRAIN_WIDTH - 6 + li t6, 3 + mv a6, sp + +5: + vsetvli a7, a4, e16, m4, ta, ma + vsetvli zero, zero, e32, m8, ta, ma + vmv.v.i v24, 0 + + sub a5, zero, t0 + mv s0, t3 + + add a3, t4, a5 + mul a3, a3, a2 + add a3, a3, t6 + slli a3, a3, 1 + add a3, a3, a0 + + vsetvli zero, zero, e16, m4, ta, ma + +6: + bge a5, zero, 9f + + sub t1, zero, t0 + slli t1, t1, 1 + add a3, a3, t1 + + sub t1, zero, t0 +7: + bgt t1, t0, 8f + + lb t5, 0(s0) + addi s0, s0, 1 + + vle16.v v16, (a3) + addi a3, a3, 2 + + vwmacc.vx v24, t5, v16 + + addi t1, t1, 1 + j 7b + +8: + slli t1, a2, 1 + add a3, a3, t1 + slli t1, t0, 1 + sub a3, a3, t1 + addi a3, a3, -2 + + addi a5, a5, 1 + j 6b + +9: + vsetvli zero, a7, e32, m8, ta, ma + vse32.v v24, (a6) + + add t6, t6, a7 + slli a3, a7, 2 + add a6, a6, a3 + sub a4, a4, a7 + bnez a4, 5b + + // scalar horizontal pass (dx < 0, dy = 0) + li a4, 3 + mv a6, sp + mul a3, t4, a2 + slli a3, a3, 1 + add a3, a3, a0 + +10: + li a7, GRAIN_WIDTH - 3 + bge a4, a7, 13f + + lw a5, 0(a6) + addi a6, a6, 4 + + mv s0, t3 + li a7, 2 + mul a7, a7, t0 + addi a7, a7, 1 + mul a7, a7, t0 + add s0, s0, a7 + + slli t6, a4, 1 + add t6, a3, t6 + sub t1, zero, t0 + +11: + bge t1, zero, 12f + + lb t5, 0(s0) + addi s0, s0, 1 + + slli a7, t1, 1 + add a7, t6, a7 + lh a7, 0(a7) + mul a7, a7, t5 + add a5, a5, a7 + + addi t1, t1, 1 + j 11b + +12: + li a7, 1 + sll a7, a7, t2 + srai a7, a7, 1 + add a5, a5, a7 + sra a5, a5, t2 + + lh t5, 0(t6) + add a5, a5, t5 + + max a5, a5, s1 + min a5, a5, s2 + + sh a5, 0(t6) + addi a4, a4, 1 + j 10b + +13: + addi t4, t4, 1 + j 4b + +14: + addi sp, sp, 512 +15: + ld s0, 0(sp) + ld s1, 8(sp) + ld s2, 16(sp) + addi sp, sp, 32 + ret +endfunc diff --git a/src/riscv/asm-offsets.h b/src/riscv/asm-offsets.h new file mode 100644 index 00000000..0f9f1e74 --- /dev/null +++ b/src/riscv/asm-offsets.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2026, VideoLAN and dav1d authors + * Copyright © 2026, Mohd Zaid + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DAV1D_SRC_RISCV_64_ASM_OFFSETS_H +#define DAV1D_SRC_RISCV_64_ASM_OFFSETS_H + +#define FGD_SEED 0 +#define FGD_AR_COEFF_LAG 92 +#define FGD_AR_COEFFS_Y 96 +#define FGD_AR_COEFFS_UV 120 +#define FGD_AR_COEFF_SHIFT 176 +#define FGD_GRAIN_SCALE_SHIFT 184 + +#define FGD_SCALING_SHIFT 88 +#define FGD_UV_MULT 188 +#define FGD_UV_LUMA_MULT 196 +#define FGD_UV_OFFSET 204 +#define FGD_CLIP_TO_RESTRICTED_RANGE 216 + +#endif /*DAV1D_SRC_RISCV_64_ASM_OFFSETS_H*/ diff --git a/src/riscv/filmgrain.h b/src/riscv/filmgrain.h new file mode 100644 index 00000000..5e7e81ce --- /dev/null +++ b/src/riscv/filmgrain.h @@ -0,0 +1,48 @@ +/* + * Copyright © 2026, VideoLAN and dav1d authors + * Copyright © 2026, Mohd Zaid + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DAV1D_SRC_RISCV_64_FILMGRAIN_H +#define DAV1D_SRC_RISCV_64_FILMGRAIN_H + +#include "src/cpu.h" +#include "src/filmgrain.h" + +decl_generate_grain_y_fn(BF(dav1d_generate_grain_y, rvv)); + +static ALWAYS_INLINE void film_grain_dsp_init_riscv(Dav1dFilmGrainDSPContext *const c){ + const unsigned flags = dav1d_get_cpu_flags(); + + if (!(flags & DAV1D_RISCV_CPU_FLAG_V)) return; + +#if BITDEPTH == 8 + c->generate_grain_y = dav1d_generate_grain_y_8bpc_rvv; +#elif BITDEPTH == 16 + c->generate_grain_y = dav1d_generate_grain_y_16bpc_rvv; +#endif +} + +#endif /* DAV1D_SRC_RISCV_FILMGRAIN_H */