From d80c53eedd398fd580c16d6c6ec42bd1cff6260f Mon Sep 17 00:00:00 2001 From: Shaun Loo Date: Sun, 13 Aug 2023 15:17:41 -0500 Subject: [PATCH 1/3] vvc_deblock: add checkasm for vvc deblocker Signed-off-by: Shaun Loo --- tests/checkasm/Makefile | 2 +- tests/checkasm/checkasm.c | 1 + tests/checkasm/checkasm.h | 1 + tests/checkasm/vvc_deblock.c | 124 +++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tests/checkasm/vvc_deblock.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 9a2105da3b3..2c5c00904f3 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -35,7 +35,7 @@ AVCODECOBJS-$(CONFIG_V210_DECODER) += v210dec.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o AVCODECOBJS-$(CONFIG_VORBIS_DECODER) += vorbisdsp.o AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o -AVCODECOBJS-$(CONFIG_VVC_DECODER) += vvc_alf.o vvc_sao.o vvc_mc.o +AVCODECOBJS-$(CONFIG_VVC_DECODER) += vvc_alf.o vvc_sao.o vvc_mc.o vvc_deblock.o CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index c4f80ece513..243c355ea87 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -179,6 +179,7 @@ static const struct { { "vvc_alf", checkasm_check_vvc_alf }, { "vvc_sao", checkasm_check_vvc_sao }, { "vvc_mc", checkasm_check_vvc_mc }, + { "vvc_deblock", checkasm_check_vvc_deblock }, #endif #endif #if CONFIG_AVFILTER diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index a82e157a4ea..12a184bb1b6 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -97,6 +97,7 @@ void checkasm_check_vorbisdsp(void); void checkasm_check_vvc_alf(void); void checkasm_check_vvc_sao(void); void checkasm_check_vvc_mc(void); +void checkasm_check_vvc_deblock(void); struct CheckasmPerf; diff --git a/tests/checkasm/vvc_deblock.c b/tests/checkasm/vvc_deblock.c new file mode 100644 index 00000000000..853e4a19b37 --- /dev/null +++ b/tests/checkasm/vvc_deblock.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2023 Shaun Loo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#include "libavcodec/avcodec.h" + +#include "libavcodec/vvc/vvcdsp.h" +#include "libavcodec/vvc/vvcdec.h" + +#include "checkasm.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define BUF_STRIDE (8 * 2) +#define BUF_LINES (8) +#define BUF_OFFSET (BUF_STRIDE * BUF_LINES) +#define BUF_SIZE (BUF_STRIDE * BUF_LINES + BUF_OFFSET * 2) + +#define randomize_buffers(buf0, buf1, size) \ + do { \ + uint32_t mask = pixel_mask[(bit_depth - 8) >> 1]; \ + int k; \ + for (k = 0; k < size; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + k, r); \ + AV_WN32A(buf1 + k, r); \ + } \ + } while (0) + +static void check_deblock_chroma(VVCDSPContext *h, int bit_depth) +{ + // To-do: figure out values to test this properly + int beta = 0; + int32_t tc = 0; + // no_p and no_q must be 0 for the simpler asm version + uint8_t no_p = 0; + uint8_t no_q = 0; + // Shift == 0 for now, we're only writing the most simple + // version + int shift = 0; + // Assembly version is only called (for now) if max_len_p != 3 && max_len_q != 3, + // labelled as "weak." HEVC has a similar hack. max_len_p == 0 || max_len_q == 0 + // will trigger immediate exit, so 1 will have to do. + int max_len_p = 1; + int max_len_q = 1; + + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, + int shift,uint8_t no_p, uint8_t no_q, int max_len_p, int max_len_q); + if (check_func(h->lf.filter_chroma[0], "vvc_h_loop_filter_chroma%d weak", bit_depth)) { + for (int i = 0; i < 4; i++) { + randomize_buffers(buf0, buf1, BUF_SIZE); + // Largest betatable value is 88, see vvc_filter.c + beta = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + tc = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + + call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + call_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + } + bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, no_p, no_q, shift, max_len_p, max_len_q); + } + + if (check_func(h->lf.filter_chroma[1], "vvc_v_loop_filter_chroma%d", bit_depth)) { + int diff = 0; + max_len_p = 2; + max_len_q = 2; + for (int i = 0; i < 4; i++) { + randomize_buffers(buf0, buf1, BUF_SIZE); + // Largest betatable value is 88, see vvc_filter.c + beta = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + tc = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + + call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + call_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + if (diff = (memcmp(buf0, buf1, BUF_SIZE))) { + { + printf("diff: %d\n", diff); + fail(); + } + + } + + } + bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, no_p, no_q, shift, max_len_p, max_len_q); + } +} + +void checkasm_check_vvc_deblock(void) +{ + int bit_depth; + + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { + VVCDSPContext h; + ff_vvc_dsp_init(&h, bit_depth); + check_deblock_chroma(&h, bit_depth); + } + report("chroma"); +} From fe34cb470cb7d46cc68539456a609024df5638b7 Mon Sep 17 00:00:00 2001 From: Shaun Loo Date: Mon, 21 Aug 2023 20:52:26 -0500 Subject: [PATCH 2/3] vvc_deblock: add simple AVX2-accelerated chroma deblocker Signed-off-by: Shaun Loo --- libavcodec/vvc/vvc_filter.c | 19 +- libavcodec/vvc/vvc_filter_template.c | 2 + libavcodec/vvc/vvcdsp.h | 2 + libavcodec/x86/Makefile | 3 +- libavcodec/x86/vvc_deblock.asm | 402 +++++++++++++++++++++++++++ libavcodec/x86/vvcdsp_init.c | 18 ++ 6 files changed, 441 insertions(+), 5 deletions(-) create mode 100644 libavcodec/x86/vvc_deblock.asm diff --git a/libavcodec/vvc/vvc_filter.c b/libavcodec/vvc/vvc_filter.c index ab6d75d06f7..12b39d5a42b 100644 --- a/libavcodec/vvc/vvc_filter.c +++ b/libavcodec/vvc/vvc_filter.c @@ -921,8 +921,13 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0) fc->vvcdsp.lf.filter_luma[1](src, fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, 0); } else { - fc->vvcdsp.lf.filter_chroma[1](src, - fc->frame->linesize[c_idx], beta, tc, no_p, no_q, vs, max_len_p, max_len_q); + if (vs || (no_p || no_q) || (max_len_p == 3 || max_len_q == 3) || (!max_len_p || !max_len_q)) { + fc->vvcdsp.lf.filter_chroma_c[1](src, + fc->frame->linesize[c_idx], beta, tc, no_p, no_q, vs, max_len_p, max_len_q); + } else { + fc->vvcdsp.lf.filter_chroma_c[1](src, + fc->frame->linesize[c_idx], beta, tc, no_p, no_q, vs, max_len_p, max_len_q); + } } } } @@ -990,8 +995,14 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0) fc->vvcdsp.lf.filter_luma[0](src, fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge); } else { - fc->vvcdsp.lf.filter_chroma[0](src, fc->frame->linesize[c_idx], beta, - tc, no_p, no_q, hs, max_len_p, max_len_q); + if (hs || (no_p || no_q) || (!max_len_p || !max_len_q) || (max_len_p == 3 || max_len_q == 3)) { + fc->vvcdsp.lf.filter_chroma_c[0](src, fc->frame->linesize[c_idx], beta, + tc, no_p, no_q, hs, max_len_p, max_len_q); + } else { + fc->vvcdsp.lf.filter_chroma[0](src, fc->frame->linesize[c_idx], beta, + tc, no_p, no_q, hs, max_len_p, max_len_q); + } + } } } diff --git a/libavcodec/vvc/vvc_filter_template.c b/libavcodec/vvc/vvc_filter_template.c index 2ce3e93ff1e..6cea412ae51 100644 --- a/libavcodec/vvc/vvc_filter_template.c +++ b/libavcodec/vvc/vvc_filter_template.c @@ -1066,6 +1066,8 @@ static void FUNC(ff_vvc_lf_dsp_init)(VVCLFDSPContext *const lf) lf->filter_luma[1] = FUNC(vvc_v_loop_filter_luma); lf->filter_chroma[0] = FUNC(vvc_h_loop_filter_chroma); lf->filter_chroma[1] = FUNC(vvc_v_loop_filter_chroma); + lf->filter_chroma_c[0] = FUNC(vvc_h_loop_filter_chroma); + lf->filter_chroma_c[1] = FUNC(vvc_v_loop_filter_chroma); } static void FUNC(ff_vvc_sao_dsp_init)(VVCSAODSPContext *const sao) diff --git a/libavcodec/vvc/vvcdsp.h b/libavcodec/vvc/vvcdsp.h index cb1c7c33121..0ad1b41ec86 100644 --- a/libavcodec/vvc/vvcdsp.h +++ b/libavcodec/vvc/vvcdsp.h @@ -130,6 +130,8 @@ typedef struct VVCLFDSPContext { uint8_t no_p, uint8_t no_q, uint8_t max_len_p, uint8_t max_len_q, int hor_ctu_edge); void (*filter_chroma[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, int max_len_p, int max_len_q); + void (*filter_chroma_c[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, + uint8_t no_p, uint8_t no_q, int shift, int max_len_p, int max_len_q); } VVCLFDSPContext; struct SAOParams; diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index 71a1cdf63e7..84fe4cfddd3 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -206,5 +206,6 @@ X86ASM-OBJS-$(CONFIG_VP9_DECODER) += x86/vp9intrapred.o \ X86ASM-OBJS-$(CONFIG_VVC_DECODER) += x86/vvc_alf.o \ x86/vvc_sao.o \ x86/vvc_sao_10bit.o \ - x86/vvc_mc.o + x86/vvc_mc.o \ + x86/vvc_deblock.o X86ASM-OBJS-$(CONFIG_WEBP_DECODER) += x86/vp8dsp.o diff --git a/libavcodec/x86/vvc_deblock.asm b/libavcodec/x86/vvc_deblock.asm new file mode 100644 index 00000000000..58153bc71f7 --- /dev/null +++ b/libavcodec/x86/vvc_deblock.asm @@ -0,0 +1,402 @@ +;***************************************************************************** +;* AVX2-optimized VVC deblocking code +;***************************************************************************** +;* Copyright (C) 2013 VTT +;* Copyright (C) 2023 Shaun Loo +;* +;* Authors: Seppo Tomperi +;* Shaun Loo +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_1023 +%define pw_pixel_max_10 pw_1023 +pw_pixel_max_12: times 8 dw ((1 << 12)-1) +pw_m2: times 8 dw -2 +pd_1 : times 4 dd 1 +pw_2 : times 8 dw 2 +pd_2 : times 4 dd 2 + +cextern pw_4 +cextern pw_8 +cextern pw_m1 + +SECTION .text +INIT_XMM avx2 + +; in: 8 rows of 4 bytes in %0..%8 +; out: 4 rows of 8 words in m0..m3 +%macro TRANSPOSE4x8B_LOAD 8 + movd m0, %1 + movd m2, %2 + movd m1, %3 + movd m3, %4 + + punpcklbw m0, m2 + punpcklbw m1, m3 + punpcklwd m0, m1 + + movd m4, %5 + movd m6, %6 + movd m5, %7 + movd m3, %8 + + punpcklbw m4, m6 + punpcklbw m5, m3 + punpcklwd m4, m5 + + punpckhdq m2, m0, m4 + punpckldq m0, m4 + + pxor m5, m5 + punpckhbw m1, m0, m5 + punpcklbw m0, m5 + punpckhbw m3, m2, m5 + punpcklbw m2, m5 +%endmacro + +; in: 4 rows of 8 words in m0..m3 +; out: 8 rows of 4 bytes in %1..%8 +%macro TRANSPOSE8x4B_STORE 8 + packuswb m0, m2 + packuswb m1, m3 + SBUTTERFLY bw, 0, 1, 2 + SBUTTERFLY wd, 0, 1, 2 + + movd %1, m0 + pshufd m0, m0, 0x39 + movd %2, m0 + pshufd m0, m0, 0x39 + movd %3, m0 + pshufd m0, m0, 0x39 + movd %4, m0 + + movd %5, m1 + pshufd m1, m1, 0x39 + movd %6, m1 + pshufd m1, m1, 0x39 + movd %7, m1 + pshufd m1, m1, 0x39 + movd %8, m1 +%endmacro + +; in: 8 rows of 4 words in %4..%11 +; out: 4 rows of 8 words in m0..m3 +%macro TRANSPOSE4x8W_LOAD 8 + movq m0, %1 + movq m2, %2 + movq m1, %3 + movq m3, %4 + + punpcklwd m0, m2 + punpcklwd m1, m3 + punpckhdq m2, m0, m1 + punpckldq m0, m1 + + movq m4, %5 + movq m6, %6 + movq m5, %7 + movq m3, %8 + + punpcklwd m4, m6 + punpcklwd m5, m3 + punpckhdq m6, m4, m5 + punpckldq m4, m5 + + punpckhqdq m1, m0, m4 + punpcklqdq m0, m4 + punpckhqdq m3, m2, m6 + punpcklqdq m2, m6 + +%endmacro + +; in: 4 rows of 8 words in m0..m3 +; out: 8 rows of 4 words in %1..%8 +%macro TRANSPOSE8x4W_STORE 9 + TRANSPOSE4x4W 0, 1, 2, 3, 4 + + pxor m5, m5; zeros reg + CLIPW m0, m5, %9 + CLIPW m1, m5, %9 + CLIPW m2, m5, %9 + CLIPW m3, m5, %9 + + movq %1, m0 + movhps %2, m0 + movq %3, m1 + movhps %4, m1 + movq %5, m2 + movhps %6, m2 + movq %7, m3 + movhps %8, m3 +%endmacro + +; in: 8 rows of 8 bytes in %1..%8 +; out: 8 rows of 8 words in m0..m7 +%macro TRANSPOSE8x8B_LOAD 8 + movq m7, %1 + movq m2, %2 + movq m1, %3 + movq m3, %4 + + punpcklbw m7, m2 + punpcklbw m1, m3 + punpcklwd m3, m7, m1 + punpckhwd m7, m1 + + movq m4, %5 + movq m6, %6 + movq m5, %7 + movq m15, %8 + + punpcklbw m4, m6 + punpcklbw m5, m15 + punpcklwd m9, m4, m5 + punpckhwd m4, m5 + + punpckldq m1, m3, m9; 0, 1 + punpckhdq m3, m9; 2, 3 + + punpckldq m5, m7, m4; 4, 5 + punpckhdq m7, m4; 6, 7 + + pxor m13, m13 + + punpcklbw m0, m1, m13; 0 in 16 bit + punpckhbw m1, m13; 1 in 16 bit + + punpcklbw m2, m3, m13; 2 + punpckhbw m3, m13; 3 + + punpcklbw m4, m5, m13; 4 + punpckhbw m5, m13; 5 + + punpcklbw m6, m7, m13; 6 + punpckhbw m7, m13; 7 +%endmacro + +; in: 8 rows of 8 words in m0..m8 +; out: 8 rows of 8 bytes in %1..%8 +%macro TRANSPOSE8x8B_STORE 8 + packuswb m0, m4 + packuswb m1, m5 + packuswb m2, m6 + packuswb m3, m7 + TRANSPOSE2x4x4B 0, 1, 2, 3, 4 + + movq %1, m0 + movhps %2, m0 + movq %3, m1 + movhps %4, m1 + movq %5, m2 + movhps %6, m2 + movq %7, m3 + movhps %8, m3 +%endmacro + +; in: 8 rows of 8 words in %1..%8 +; out: 8 rows of 8 words in m0..m7 +%macro TRANSPOSE8x8W_LOAD 8 + movdqu m0, %1 + movdqu m1, %2 + movdqu m2, %3 + movdqu m3, %4 + movdqu m4, %5 + movdqu m5, %6 + movdqu m6, %7 + movdqu m7, %8 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%endmacro + +; in: 8 rows of 8 words in m0..m8 +; out: 8 rows of 8 words in %1..%8 +%macro TRANSPOSE8x8W_STORE 9 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 + + pxor m8, m8 + CLIPW m0, m8, %9 + CLIPW m1, m8, %9 + CLIPW m2, m8, %9 + CLIPW m3, m8, %9 + CLIPW m4, m8, %9 + CLIPW m5, m8, %9 + CLIPW m6, m8, %9 + CLIPW m7, m8, %9 + + movdqu %1, m0 + movdqu %2, m1 + movdqu %3, m2 + movdqu %4, m3 + movdqu %5, m4 + movdqu %6, m5 + movdqu %7, m6 + movdqu %8, m7 +%endmacro + +; in: %2 clobbered +; out: %1 +; mask in m11 +; clobbers m10 +%macro MASKED_COPY 2 + pand %2, m11 ; and mask + pandn m10, m11, %1; and -mask + por %2, m10 + mova %1, %2 +%endmacro + +; in: %2 clobbered +; out: %1 +; mask in %3, will be clobbered +%macro MASKED_COPY2 3 + pand %2, %3 ; and mask + pandn %3, %1; and -mask + por %2, %3 + mova %1, %2 +%endmacro + +ALIGN 16 +; input in m0 ... m3 and tcs in r2. Output in m1 and m2 +%macro CHROMA_DEBLOCK_BODY 1 + psubw m4, m2, m1; q0 - p0 + psubw m5, m0, m3; p1 - q1 + psllw m4, 2; << 2 + paddw m5, m4; + + ;tc calculations + movq m6, tcq; tc + punpcklwd m6, m6 + pshufd m6, m6, 0xA0 +%if %1 == 8 + paddw m6, [pw_2] + psraw m6, 2 +%elif %1 == 12 + psllw m6, 2 +%endif + psignw m4, m6, [pw_m1] + ;end tc calculations + + paddw m5, [pw_4]; +4 + psraw m5, 3; >> 3 + + pmaxsw m5, m4 + pminsw m5, m6 + paddw m1, m5; p0 + delta0 + psubw m2, m5; q0 - delta0 +%endmacro + + + +%macro LOOP_FILTER_CHROMA 0 + +; void ff_vvc_h_loop_filter_chroma_(uint8_t *pix, ptrdiff_t stride, +; int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, +; int max_len_p, int max_len_q) + +cglobal vvc_h_loop_filter_chroma_8, 5, 6, 7, pix, stride, beta, tc, shift, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movq m0, [pix0q]; p1 + movq m1, [pix0q+strideq]; p0 + movq m2, [pixq]; q0 + movq m3, [pixq+strideq]; q1 + pxor m5, m5; zeros reg + punpcklbw m0, m5 + punpcklbw m1, m5 + punpcklbw m2, m5 + punpcklbw m3, m5 + CHROMA_DEBLOCK_BODY 8 + packuswb m1, m2 + movh[pix0q+strideq], m1 + movhps [pixq], m1 + RET + +cglobal vvc_h_loop_filter_chroma_10, 5, 6, 7, pix, stride, beta, tc, shift, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movu m0, [pix0q]; p1 + movu m1, [pix0q+strideq]; p0 + movu m2, [pixq]; q0 + movu m3, [pixq+strideq]; q1 + CHROMA_DEBLOCK_BODY 10 + pxor m5, m5; zeros reg + CLIPW m1, m5, [pw_pixel_max_10] + CLIPW m2, m5, [pw_pixel_max_10] + movu [pix0q+strideq], m1 + movu [pixq], m2 + RET + +cglobal vvc_h_loop_filter_chroma_12, 4, 5, 7, pix, stride, beta, tc, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movu m0, [pix0q]; p1 + movu m1, [pix0q+strideq]; p0 + movu m2, [pixq]; q0 + movu m3, [pixq+strideq]; q1 + CHROMA_DEBLOCK_BODY 12 + pxor m5, m5; zeros reg + CLIPW m1, m5, [pw_pixel_max_12] + CLIPW m2, m5, [pw_pixel_max_12] + movu [pix0q+strideq], m1 + movu [pixq], m2 + RET + +; void ff_vvc_v_loop_filter_chroma_(uint8_t *pix, ptrdiff_t stride, +; int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, +; int max_len_p, int max_len_q) + +cglobal vvc_v_loop_filter_chroma_8, 5, 7, 7, pix, stride, beta, tc, shift, pix0, r3stride + sub pixq, 2 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8B_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 8 + TRANSPOSE8x4B_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq) + RET + +cglobal vvc_v_loop_filter_chroma_10, 5, 7, 7, pix, stride, beta, tc, shift, pix0, r3stride + sub pixq, 4 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8W_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 10 + TRANSPOSE8x4W_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq), [pw_pixel_max_10] + RET + +cglobal vvc_v_loop_filter_chroma_12, 4, 6, 7, pix, stride, beta, tc, pix0, r3stride + sub pixq, 4 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8W_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 12 + TRANSPOSE8x4W_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq), [pw_pixel_max_12] + RET + +%endmacro + +INIT_XMM avx2 +LOOP_FILTER_CHROMA diff --git a/libavcodec/x86/vvcdsp_init.c b/libavcodec/x86/vvcdsp_init.c index a5849e3a2ed..b13fec0677d 100644 --- a/libavcodec/x86/vvcdsp_init.c +++ b/libavcodec/x86/vvcdsp_init.c @@ -196,6 +196,18 @@ SAO_EDGE_FILTER_FUNCS(12, avx2) c->sao.edge_filter[8] = ff_vvc_sao_edge_filter_128_##bitd##_##opt; \ } while (0) +#define LOOP_FILTER_FUNCS(bitd, opt) \ +void ff_vvc_h_loop_filter_chroma_##bitd##_##opt(uint8_t *pix, ptrdiff_t stride, \ + int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, \ + int max_len_p, int max_len_q); \ +void ff_vvc_v_loop_filter_chroma_##bitd##_##opt(uint8_t *pix, ptrdiff_t stride, \ + int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, \ + int max_len_p, int max_len_q); \ + +LOOP_FILTER_FUNCS(8, avx2) +LOOP_FILTER_FUNCS(10, avx2) +LOOP_FILTER_FUNCS(12, avx2) + #define PUT_VVC_LUMA_8_FUNC(dir, opt) \ void ff_vvc_put_vvc_luma_##dir##_8_##opt(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride, \ const int height, const intptr_t mx, const intptr_t my, const int width, \ @@ -252,15 +264,21 @@ void ff_vvc_dsp_init_x86(VVCDSPContext *const c, const int bit_depth) PUT_VVC_LUMA_INIT(8, avx2); c->sao.band_filter[0] = ff_vvc_sao_band_filter_8_8_avx2; c->sao.band_filter[1] = ff_vvc_sao_band_filter_16_8_avx2; + c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_8_avx2; + c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_8_avx2; break; case 10: ALF_DSP(10); PUT_VVC_LUMA_INIT(10, avx2); c->sao.band_filter[0] = ff_vvc_sao_band_filter_8_10_avx2; + c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_10_avx2; + c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_10_avx2; break; case 12: ALF_DSP(12); PUT_VVC_LUMA_INIT(12, avx2); + c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_12_avx2; + c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_12_avx2; break; default: break; From 3fe3b4338d9805a1c6cd585bc9bbceb0dfb2b4e7 Mon Sep 17 00:00:00 2001 From: Shaun Loo Date: Tue, 22 Aug 2023 03:47:29 -0500 Subject: [PATCH 3/3] vvc_deblock: add checkasm for vvc deblocker Signed-off-by: Shaun Loo --- tests/checkasm/vvc_deblock.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/checkasm/vvc_deblock.c b/tests/checkasm/vvc_deblock.c index 853e4a19b37..46fa75f03ce 100644 --- a/tests/checkasm/vvc_deblock.c +++ b/tests/checkasm/vvc_deblock.c @@ -71,7 +71,7 @@ static void check_deblock_chroma(VVCDSPContext *h, int bit_depth) declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, int shift,uint8_t no_p, uint8_t no_q, int max_len_p, int max_len_q); - if (check_func(h->lf.filter_chroma[0], "vvc_h_loop_filter_chroma%d weak", bit_depth)) { + if (check_func(h->lf.filter_chroma[0], "vvc_h_loop_filter_chroma_%d", bit_depth)) { for (int i = 0; i < 4; i++) { randomize_buffers(buf0, buf1, BUF_SIZE); // Largest betatable value is 88, see vvc_filter.c @@ -86,7 +86,7 @@ static void check_deblock_chroma(VVCDSPContext *h, int bit_depth) bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, no_p, no_q, shift, max_len_p, max_len_q); } - if (check_func(h->lf.filter_chroma[1], "vvc_v_loop_filter_chroma%d", bit_depth)) { + if (check_func(h->lf.filter_chroma[1], "vvc_v_loop_filter_chroma_%d", bit_depth)) { int diff = 0; max_len_p = 2; max_len_q = 2; @@ -99,11 +99,7 @@ static void check_deblock_chroma(VVCDSPContext *h, int bit_depth) call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); call_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); if (diff = (memcmp(buf0, buf1, BUF_SIZE))) { - { - printf("diff: %d\n", diff); - fail(); - } - + fail(); } }