[x264-devel] [patch] SSE2 motion compensation [pixel_avg w16/w20, mc_copy w16, pixel_avg_16x16, pixel_avg_16x8] + pixel_avg w12

Jason Garrett-Glaser darkshikari at gmail.com
Mon Mar 3 01:40:42 CET 2008


Index: common/mc.c
===================================================================
--- common/mc.c    (revision 745)
+++ common/mc.c    (working copy)
@@ -377,7 +377,9 @@
 #ifdef HAVE_MMX
     x264_mc_init_mmx( cpu, pf );
     if( cpu&X264_CPU_MMXEXT )
+    {
         pf->mc_chroma = x264_mc_chroma_mmxext;
+    }
 #endif
 #ifdef ARCH_PPC
     if( cpu&X264_CPU_ALTIVEC )
Index: common/i386/mc-a.asm
===================================================================
--- common/i386/mc-a.asm    (revision 745)
+++ common/i386/mc-a.asm    (working copy)
@@ -128,21 +128,23 @@
     movdqa [eax+ebx], xmm1
 AVG_END

-%macro AVGH 2
-cglobal x264_pixel_avg_%1x%2_mmxext
+%macro AVGH 3
+cglobal x264_pixel_avg_%1x%2_%3
     push esi
     mov esi, %2
-    jmp x264_pixel_avg_w%1_mmxext
+    jmp x264_pixel_avg_w%1_%3
 %endmacro

-AVGH 16, 16
-AVGH 16, 8
-AVGH 8, 16
-AVGH 8, 8
-AVGH 8, 4
-AVGH 4, 8
-AVGH 4, 4
-AVGH 4, 2
+AVGH 16, 16, mmxext
+AVGH 16, 8, mmxext
+AVGH 8, 16, mmxext
+AVGH 8, 8, mmxext
+AVGH 8, 4, mmxext
+AVGH 4, 8, mmxext
+AVGH 4, 4, mmxext
+AVGH 4, 2, mmxext
+AVGH 16, 16, sse2
+AVGH 16, 8, sse2

 %macro AVG2_START 1
 cglobal %1
@@ -191,6 +193,21 @@
     movq   [eax+ebx], mm1
 AVG2_END

+AVG2_START x264_pixel_avg2_w12_mmxext
+    movq   mm0, [ecx]
+    movd   mm1, [ecx+8]
+    movq   mm2, [ecx+edx]
+    movd   mm3, [ecx+edx+8]
+    pavgb  mm0, [ecx+edi]
+    pavgb  mm1, [ecx+edi+8]
+    pavgb  mm2, [ecx+ebp]
+    pavgb  mm3, [ecx+ebp+8]
+    movq   [eax], mm0
+    movd   [eax+8], mm1
+    movq   [eax+ebx], mm2
+    movd   [eax+ebx+8], mm3
+AVG2_END
+
 AVG2_START x264_pixel_avg2_w16_mmxext
     movq   mm0, [ecx]
     movq   mm1, [ecx+8]
@@ -227,7 +244,33 @@
     movd   [eax+ebx+16], mm5
 AVG2_END

+AVG2_START x264_pixel_avg2_w16_sse2
+    movdqu xmm0, [ecx]
+    movdqu xmm2, [ecx+edi]
+    movdqu xmm1, [ecx+edx]
+    movdqu xmm3, [ecx+ebp]
+    pavgb  xmm0, xmm2
+    pavgb  xmm1, xmm3
+    movdqa [eax], xmm0
+    movdqa [eax+ebx], xmm1
+AVG2_END

+AVG2_START x264_pixel_avg2_w20_sse2
+    movdqu xmm0, [ecx]
+    movdqu xmm2, [ecx+edi]
+    movdqu xmm1, [ecx+edx]
+    movdqu xmm3, [ecx+ebp]
+    movd   mm2,  [ecx+16]
+    movd   mm5,  [ecx+edx+16]
+    pavgb  xmm0, xmm2
+    pavgb  xmm1, xmm3
+    pavgb  mm2,  [ecx+edi+16]
+    pavgb  mm5,  [ecx+ebp+16]
+    movdqa [eax], xmm0
+    movd   [eax+16], mm2
+    movdqa [eax+ebx], xmm1
+    movd   [eax+ebx+16], mm5
+AVG2_END

 ;=============================================================================
 ; weighted prediction
Index: common/i386/mc-c.c
===================================================================
--- common/i386/mc-c.c    (revision 745)
+++ common/i386/mc-c.c    (working copy)
@@ -28,6 +28,8 @@
 #include "common/common.h"

 /* NASM functions */
+extern void x264_pixel_avg_16x16_sse2( uint8_t *, int, uint8_t *, int );
+extern void x264_pixel_avg_16x8_sse2( uint8_t *, int, uint8_t *, int );
 extern void x264_pixel_avg_16x16_mmxext( uint8_t *, int, uint8_t *, int );
 extern void x264_pixel_avg_16x8_mmxext( uint8_t *, int, uint8_t *, int );
 extern void x264_pixel_avg_8x16_mmxext( uint8_t *, int, uint8_t *, int );
@@ -38,8 +40,11 @@
 extern void x264_pixel_avg_4x2_mmxext( uint8_t *, int, uint8_t *, int );
 extern void x264_pixel_avg2_w4_mmxext( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
 extern void x264_pixel_avg2_w8_mmxext( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
+extern void x264_pixel_avg2_w12_mmxext( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
 extern void x264_pixel_avg2_w16_mmxext( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
 extern void x264_pixel_avg2_w20_mmxext( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
+extern void x264_pixel_avg2_w16_sse2( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
+extern void x264_pixel_avg2_w20_sse2( uint8_t *, int, uint8_t *, int,
uint8_t *, int );
 extern void x264_pixel_avg_weight_4x4_mmxext( uint8_t *, int, uint8_t *,
int, int );
 extern void x264_pixel_avg_weight_w8_mmxext( uint8_t *, int, uint8_t *,
int, int, int );
 extern void x264_pixel_avg_weight_w16_mmxext( uint8_t *, int, uint8_t *,
int, int, int );
@@ -69,9 +74,9 @@
     NULL,
     x264_pixel_avg2_w4_mmxext,
     x264_pixel_avg2_w8_mmxext,
+    x264_pixel_avg2_w12_mmxext,
     x264_pixel_avg2_w16_mmxext,
-    x264_pixel_avg2_w16_mmxext,
-    x264_pixel_avg2_w20_mmxext,
+    x264_pixel_avg2_w20_mmxext
 };
 static void (* const x264_mc_copy_wtab_mmx[5])( uint8_t *, int, uint8_t *,
int, int ) =
 {
@@ -81,56 +86,80 @@
     NULL,
     x264_mc_copy_w16_mmx
 };
+static void (* const x264_pixel_avg_wtab_sse2[6])( uint8_t *, int, uint8_t
*, int, uint8_t *, int ) =
+{
+    NULL,
+    x264_pixel_avg2_w4_mmxext,
+    x264_pixel_avg2_w8_mmxext,
+    x264_pixel_avg2_w12_mmxext,
+    x264_pixel_avg2_w16_sse2,
+    x264_pixel_avg2_w20_sse2
+};
+static void (* const x264_mc_copy_wtab_sse2[5])( uint8_t *, int, uint8_t *,
int, int ) =
+{
+    NULL,
+    x264_mc_copy_w4_mmx,
+    x264_mc_copy_w8_mmx,
+    NULL,
+    x264_mc_copy_w16_sse2
+};
 static const int hpel_ref0[16] = {0,1,1,1,0,1,1,1,2,3,3,3,0,1,1,1};
 static const int hpel_ref1[16] = {0,0,0,0,2,2,3,2,2,2,3,2,2,2,3,2};

-void mc_luma_mmxext( uint8_t *dst,    int i_dst_stride,
-                     uint8_t *src[4], int i_src_stride,
-                     int mvx, int mvy,
-                     int i_width, int i_height )
-{
-    int qpel_idx = ((mvy&3)<<2) + (mvx&3);
-    int offset = (mvy>>2)*i_src_stride + (mvx>>2);
-    uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) *
i_src_stride;
-
-    if( qpel_idx & 5 ) /* qpel interpolation needed */
-    {
-        uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
-        x264_pixel_avg_wtab_mmxext[i_width>>2](
-                dst, i_dst_stride, src1, i_src_stride,
-                src2, i_height );
-    }
-    else
-    {
-        x264_mc_copy_wtab_mmx[i_width>>2](
-                dst, i_dst_stride, src1, i_src_stride, i_height );
-    }
+#define MC_LUMA(name,instr1,instr2)\
+void mc_luma_##name( uint8_t *dst,    int i_dst_stride,\
+                  uint8_t *src[4], int i_src_stride,\
+                  int mvx, int mvy,\
+                  int i_width, int i_height )\
+{\
+    int qpel_idx = ((mvy&3)<<2) + (mvx&3);\
+    int offset = (mvy>>2)*i_src_stride + (mvx>>2);\
+    uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) *
i_src_stride;\
+    if( qpel_idx & 5 ) /* qpel interpolation needed */\
+    {\
+        uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) ==
3);\
+        x264_pixel_avg_wtab_##instr1[i_width>>2](\
+                dst, i_dst_stride, src1, i_src_stride,\
+                src2, i_height );\
+    }\
+    else\
+    {\
+        x264_mc_copy_wtab_##instr2[i_width>>2](\
+                dst, i_dst_stride, src1, i_src_stride, i_height );\
+    }\
 }

-uint8_t *get_ref_mmxext( uint8_t *dst,   int *i_dst_stride,
-                         uint8_t *src[4], int i_src_stride,
-                         int mvx, int mvy,
-                         int i_width, int i_height )
-{
-    int qpel_idx = ((mvy&3)<<2) + (mvx&3);
-    int offset = (mvy>>2)*i_src_stride + (mvx>>2);
-    uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) *
i_src_stride;
-
-    if( qpel_idx & 5 ) /* qpel interpolation needed */
-    {
-        uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
-        x264_pixel_avg_wtab_mmxext[i_width>>2](
-                dst, *i_dst_stride, src1, i_src_stride,
-                src2, i_height );
-        return dst;
-    }
-    else
-    {
-        *i_dst_stride = i_src_stride;
-        return src1;
-    }
+MC_LUMA(mmxext,mmxext,mmx)
+MC_LUMA(sse2,sse2,sse2)
+#include "bench.h"
+#define GET_REF(name)\
+uint8_t *get_ref_##name( uint8_t *dst,   int *i_dst_stride,\
+                         uint8_t *src[4], int i_src_stride,\
+                         int mvx, int mvy,\
+                         int i_width, int i_height )\
+{\
+    int qpel_idx = ((mvy&3)<<2) + (mvx&3);\
+    int offset = (mvy>>2)*i_src_stride + (mvx>>2);\
+    uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) *
i_src_stride;\
+    if( qpel_idx & 5 ) /* qpel interpolation needed */\
+    {\
+        uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) ==
3);\
+        START_TIMER;\
+        x264_pixel_avg_wtab_##name[i_width>>2](\
+                dst, *i_dst_stride, src1, i_src_stride,\
+                src2, i_height );\
+        if(i_width>>2 == 5) STOP_TIMER("w20");\
+        return dst;\
+    }\
+    else\
+    {\
+        *i_dst_stride = i_src_stride;\
+        return src1;\
+    }\
 }

+GET_REF(mmxext)
+GET_REF(sse2)

 void x264_mc_init_mmx( int cpu, x264_mc_functions_t *pf )
 {
@@ -169,6 +198,12 @@

     pf->prefetch_fenc = x264_prefetch_fenc_mmxext;
     pf->prefetch_ref  = x264_prefetch_ref_mmxext;
-
-    /* todo: use sse2 */
+    // disable on AMD processors since it is slower
+    if( (cpu&X264_CPU_SSE2) && !(cpu&X264_CPU_3DNOW) )
+    {
+        pf->avg[PIXEL_16x16] = x264_pixel_avg_16x16_sse2;
+        pf->avg[PIXEL_16x8]  = x264_pixel_avg_16x8_sse2;
+        pf->mc_luma = mc_luma_sse2;
+        pf->get_ref = get_ref_sse2;
+    }
 }
Index: tools/checkasm.c
===================================================================
--- tools/checkasm.c    (revision 745)
+++ tools/checkasm.c    (working copy)
@@ -407,8 +407,8 @@
     uint8_t *src     = &buf1[2*32+2];
     uint8_t *src2[4] = { &buf1[2*32+2],  &buf1[6*32+2],
                          &buf1[10*32+2], &buf1[14*32+2] };
-    uint8_t *dst1    = &buf3[2*32+2];
-    uint8_t *dst2    = &buf4[2*32+2];
+    uint8_t *dst1    = &buf3[2*32];
+    uint8_t *dst2    = &buf4[2*32];

     int dx, dy, i, j, w;
     int ret = 0, ok, used_asm;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.videolan.org/pipermail/x264-devel/attachments/20080302/e64ed916/attachment-0001.htm 


More information about the x264-devel mailing list