mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-10-28 15:19:38 +03:00
swscale/x86/ops: rewrite based on uops_macros.h
This is a ground-up refactor of the existing x86 ops code, using the new uops macros to auto-generate every single kernel instance without guesswork. While I was at it, I also cleaned up the file a bit and made sure we have only a single, consistent way of writing/defining the kernels. This also gets rid of some of the old boilerplate like decl_pattern. Most kernels are trivial ports, but a few deserve attention or note: - SWS_UOP_LINEAR is now generated more efficiently, thanks to the distinction between 0/1/arbitrary components. I also rewrote the code to keep track of whether the output was initialized yet or not, which lets us skip the initial `xorps` and `addps` for the first component. - SWS_UOP_PERMUTE is generated automatically by using some NASM logic to detect permutation cycles and emit the minimal sequence of `mova` instructions. SWS_UOP_COPY, on the other hand, is implemented naively. I originally had a more complex implementation that could handle both, but I decided it really isn't worth the complication just to save 2-3 cycles. - SWS_UOP_SCALE now has a native 8-bit implementation, which is faster than falling back to C code. - SWS_UOP_SWAP_BYTES is no longer compiled as a type-agnostic pshufb, instead we hard-code the shuffle mask - SWS_UOP_DITHER is now much simpler and avoids branching etc. entirely Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
1037
libswscale/x86/ops.c
1037
libswscale/x86/ops.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -70,9 +70,9 @@
|
||||
; if we load 8-bit values and convert them to 32-bit floats internally, then
|
||||
; we would have an operation chain which combines an SSE4 V2=0 u8 kernel (128
|
||||
; bits = 16 pixels) with an AVX2 V2=1 f32 kernel (512 bits = 16 pixels). This
|
||||
; keeps the number of pixels being processed (the block size) constant. The
|
||||
; V2 setting is suffixed to the operation name (_m1 or _m2) during name
|
||||
; mangling.
|
||||
; keeps the number of pixels being processed (BLOCK_WIDTH) constant. The V2
|
||||
; setting is suffixed to the operation name (_m1 or _m2), along with any other
|
||||
; custom NAME_SUFFIX (e.g. for operation variants).
|
||||
;
|
||||
; This design leaves us with the following set of possibilities:
|
||||
;
|
||||
@@ -92,15 +92,7 @@
|
||||
; - 16-bit kernels: m1_avx2, m2_avx2
|
||||
; - 32-bit kernels: m2_avx2
|
||||
;
|
||||
; This is achieved by macro'ing each operation kernel and declaring it once
|
||||
; per SIMD version, and (if needed) once per V2 setting using decl_v2. (See
|
||||
; the bottom of ops_int.asm for an example)
|
||||
;
|
||||
; Finally, we overload some operation kernel to different number of components,
|
||||
; using the `decl_pattern` and `decl_common_patterns` macros. Inside these
|
||||
; kernels, the variables X, Y, Z and W will be set to 0 or 1 respectively,
|
||||
; depending on which components are active for this particular kernel instance.
|
||||
; They will receive the _pXYZW prefix during name mangling.
|
||||
; See the bottom of ops_int.asm for an example.
|
||||
|
||||
struc SwsOpExec
|
||||
.in0 resq 1
|
||||
@@ -147,17 +139,55 @@ struc SwsOpImpl
|
||||
.next resb 0
|
||||
endstruc
|
||||
|
||||
%define SWS_COMP_NONE 0
|
||||
%define SWS_COMP_ALL 0xF
|
||||
%define SWS_COMP(X) (1 << (X))
|
||||
%define SWS_COMP_TEST(mask, X) (((mask) >> X) & 1)
|
||||
%define SWS_COMP_INV(mask) ((mask) ^ SWS_COMP_ALL)
|
||||
%define SWS_COMP_ELEMS(N) ((1 << (N)) - 1)
|
||||
|
||||
;---------------------------------------------------------
|
||||
; Common macros for declaring operations
|
||||
|
||||
; Declare an operation kernel with the correct name mangling.
|
||||
%macro op 1 ; name
|
||||
%ifdef X
|
||||
%define ADD_PAT(name) p %+ X %+ Y %+ Z %+ W %+ _ %+ name
|
||||
; Declare an operation kernel, calling a provided macro to generate the body.
|
||||
; Note: This is automatically called by the DECL_*() macros
|
||||
%macro DECL_OP 5-6+ ; macro, name, type, uop, mask
|
||||
; Declare named variables for common macro parameters
|
||||
%ifdef NAME_SUFFIX
|
||||
%xdefine NAME %2 %+ NAME_SUFFIX
|
||||
%else
|
||||
%define ADD_PAT(name) name
|
||||
%xdefine NAME %2
|
||||
%endif
|
||||
%xdefine TYPE %3
|
||||
%xdefine UOP %4
|
||||
%xdefine MASK %5
|
||||
|
||||
; Declare X/Y/Z/W based on the provided mask
|
||||
%assign X SWS_COMP_TEST(MASK, 0)
|
||||
%assign Y SWS_COMP_TEST(MASK, 1)
|
||||
%assign Z SWS_COMP_TEST(MASK, 2)
|
||||
%assign W SWS_COMP_TEST(MASK, 3)
|
||||
%assign COMPS (X + Y + Z + W)
|
||||
|
||||
; Declare BYTES and BITS based on the ops type
|
||||
%ifidn TYPE, SWS_PIXEL_U8
|
||||
%assign BYTES 1
|
||||
%elifidn TYPE, SWS_PIXEL_U16
|
||||
%assign BYTES 2
|
||||
%else
|
||||
%assign BYTES 4
|
||||
%endif
|
||||
%assign BITS (BYTES * 8)
|
||||
|
||||
; Calculate block size helpers
|
||||
%ifdef V2
|
||||
%assign BLOCK_SIZE (mmsize * (1 + V2))
|
||||
%else
|
||||
%assign BLOCK_SIZE (mmsize)
|
||||
%endif
|
||||
%assign BLOCK_WIDTH (BLOCK_SIZE / BYTES)
|
||||
|
||||
; Add the correct name mangling / suffix for decl_v2
|
||||
%ifdef V2
|
||||
%if V2
|
||||
%define ADD_MUL(name) name %+ _m2
|
||||
@@ -168,12 +198,32 @@ endstruc
|
||||
%define ADD_MUL(name) name
|
||||
%endif
|
||||
|
||||
cglobal ADD_PAT(ADD_MUL(%1)), 0, 0, 0 ; already allocated by entry point
|
||||
cglobal ADD_MUL(NAME), 0, 0, 0 ; already allocated by entry point
|
||||
%1 %6 ; call the provided macro to generate the kernel body
|
||||
|
||||
%undef ADD_PAT
|
||||
%undef NAME
|
||||
%undef UOP
|
||||
%undef TYPE
|
||||
%undef MASK
|
||||
%undef X
|
||||
%undef Y
|
||||
%undef Z
|
||||
%undef W
|
||||
%undef COMPS
|
||||
%undef BYTES
|
||||
%undef BITS
|
||||
%undef BLOCK_SIZE
|
||||
%undef BLOCK_WIDTH
|
||||
%undef ADD_MUL
|
||||
%endmacro
|
||||
|
||||
; Declare a set of operations with a custom name suffix
|
||||
%macro decl_suffix 2+ ; suffix, func
|
||||
%xdefine NAME_SUFFIX %1
|
||||
%2
|
||||
%undef NAME_SUFFIX
|
||||
%endmacro
|
||||
|
||||
; Declare a set of operations with the high half enabled / disabled
|
||||
%macro decl_v2 2+ ; v2, func
|
||||
%assign V2 %1
|
||||
@@ -181,27 +231,6 @@ endstruc
|
||||
%undef V2
|
||||
%endmacro
|
||||
|
||||
; Declare an operation kernel specialized to a given subset of active components
|
||||
%macro decl_pattern 5+ ; X, Y, Z, W, func
|
||||
%assign X %1
|
||||
%assign Y %2
|
||||
%assign Z %3
|
||||
%assign W %4
|
||||
%5
|
||||
%undef X
|
||||
%undef Y
|
||||
%undef Z
|
||||
%undef W
|
||||
%endmacro
|
||||
|
||||
; Declare an operation kernel specialized to each common component pattern
|
||||
%macro decl_common_patterns 1+ ; func
|
||||
decl_pattern 1, 0, 0, 0, %1 ; y
|
||||
decl_pattern 1, 0, 0, 1, %1 ; ya
|
||||
decl_pattern 1, 1, 1, 0, %1 ; yuv
|
||||
decl_pattern 1, 1, 1, 1, %1 ; yuva
|
||||
%endmacro
|
||||
|
||||
;---------------------------------------------------------
|
||||
; Common names for the internal calling convention
|
||||
%define mx m0
|
||||
@@ -287,6 +316,9 @@ endstruc
|
||||
CONTINUE tmp0q
|
||||
%endmacro
|
||||
|
||||
;---------------------------------------------------------
|
||||
; Miscellaneous helpers
|
||||
|
||||
; Helper for inline conditionals; used to conditionally include single lines
|
||||
%macro IF 2+ ; cond, body
|
||||
%if %1
|
||||
@@ -300,3 +332,43 @@ endstruc
|
||||
%2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro shl_log2 2 ; dst, amount
|
||||
%if %2 == 64
|
||||
shl %1, 6
|
||||
%elif %2 == 32
|
||||
shl %1, 5
|
||||
%elif %2 == 16
|
||||
shl %1, 4
|
||||
%elif %2 == 8
|
||||
shl %1, 3
|
||||
%elif %2 == 4
|
||||
shl %1, 2
|
||||
%elif %2 == 2
|
||||
shl %1, 1
|
||||
%elif %2 == 1
|
||||
; no-op
|
||||
%else
|
||||
%error "Unsupported value for shl_log2"
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro assert 1-2 ; cond, message
|
||||
%if !(%1)
|
||||
%if %0 > 1
|
||||
%error %2
|
||||
%else
|
||||
%error Assertion failed: %1
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%macro assert_idn 2-3 ; expr1, expr2, message
|
||||
%ifnidn %1, %2
|
||||
%if %0 > 2
|
||||
%error %3
|
||||
%else
|
||||
%error Assertion failed: %1 == %2
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user