[x264-devel] AVX mbtree_propagate

Jason Garrett-Glaser git at videolan.org
Wed Jun 15 04:54:19 CEST 2011


x264 | branch: master | Jason Garrett-Glaser <jason at x264.com> | Tue May 17 14:50:51 2011 -0700| [1392798b74f12c9fa7a649f87eabb9cfa237d97a] | committer: Jason Garrett-Glaser

AVX mbtree_propagate
Up to ~20-30% faster than SSE2 on Sandy Bridge.

> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=1392798b74f12c9fa7a649f87eabb9cfa237d97a
---

 common/frame.c       |    2 +-
 common/macroblock.c  |    2 +-
 common/x86/mc-a2.asm |   50 ++++++++++++++++++++++++++++++++++++++++++++++++--
 common/x86/mc-c.c    |    6 ++++++
 tools/checkasm.c     |    4 ++--
 5 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/common/frame.c b/common/frame.c
index 2d56921..7356716 100644
--- a/common/frame.c
+++ b/common/frame.c
@@ -179,7 +179,7 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
                     CHECKED_MALLOCZERO( frame->lowres_mvs[j][i], 2*h->mb.i_mb_count*sizeof(int16_t) );
                     CHECKED_MALLOC( frame->lowres_mv_costs[j][i], h->mb.i_mb_count*sizeof(int) );
                 }
-            CHECKED_MALLOC( frame->i_propagate_cost, (i_mb_count+3) * sizeof(uint16_t) );
+            CHECKED_MALLOC( frame->i_propagate_cost, (i_mb_count+7) * sizeof(uint16_t) );
             for( int j = 0; j <= h->param.i_bframe+1; j++ )
                 for( int i = 0; i <= h->param.i_bframe+1; i++ )
                     CHECKED_MALLOC( frame->lowres_costs[j][i], (i_mb_count+3) * sizeof(uint16_t) );
diff --git a/common/macroblock.c b/common/macroblock.c
index 686fd50..08eea5a 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -342,7 +342,7 @@ int x264_macroblock_thread_allocate( x264_t *h, int b_lookahead )
             ((me_range*2+24) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
         scratch_size = X264_MAX3( buf_hpel, buf_ssim, buf_tesa );
     }
-    int buf_mbtree = h->param.rc.b_mb_tree * ((h->mb.i_mb_width+3)&~3) * sizeof(int);
+    int buf_mbtree = h->param.rc.b_mb_tree * ((h->mb.i_mb_width+7)&~7) * sizeof(int);
     scratch_size = X264_MAX( scratch_size, buf_mbtree );
     if( scratch_size )
         CHECKED_MALLOC( h->scratch_buffer, scratch_size );
diff --git a/common/x86/mc-a2.asm b/common/x86/mc-a2.asm
index 69b0d6a..1d42069 100644
--- a/common/x86/mc-a2.asm
+++ b/common/x86/mc-a2.asm
@@ -40,7 +40,7 @@ deinterleave_shuf: db 0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15
 
 pd_16: times 4 dd 16
 pd_0f: times 4 dd 0xffff
-pf_inv256: times 4 dd 0.00390625
+pf_inv256: times 8 dd 0.00390625
 
 pad10: times 8 dw    10*PIXEL_MAX
 pad20: times 8 dw    20*PIXEL_MAX
@@ -1630,7 +1630,7 @@ FRAME_INIT_LOWRES ssse3
 ;                             uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len )
 ;-----------------------------------------------------------------------------
 cglobal mbtree_propagate_cost_sse2, 7,7,7
-    shl        r6d, 1
+    add        r6d, r6d
     lea         r0, [r0+r6*2]
     add         r1, r6
     add         r2, r6
@@ -1673,3 +1673,49 @@ cglobal mbtree_propagate_cost_sse2, 7,7,7
     jl .loop
     REP_RET
 
+%macro INT16_TO_FLOAT 1
+    vpunpckhwd   xmm4, xmm%1, xmm7
+    vpunpcklwd  xmm%1, xmm7
+    vinsertf128 ymm%1, ymm%1, xmm4, 1
+    vcvtdq2ps   ymm%1, ymm%1
+%endmacro
+
+; FIXME: align loads/stores to 16 bytes
+cglobal mbtree_propagate_cost_avx, 7,7,8
+    add           r6d, r6d
+    lea            r0, [r0+r6*2]
+    add            r1, r6
+    add            r2, r6
+    add            r3, r6
+    add            r4, r6
+    neg            r6
+    vmovdqa      xmm5, [pw_3fff]
+    vbroadcastss ymm6, [r5]
+    vmulps       ymm6, ymm6, [pf_inv256]
+    vpxor        xmm7, xmm7
+.loop:
+    vmovdqu      xmm0, [r2+r6]       ; intra
+    vmovdqu      xmm1, [r4+r6]       ; invq
+    vmovdqu      xmm2, [r1+r6]       ; prop
+    vpand        xmm3, xmm5, [r3+r6] ; inter
+    INT16_TO_FLOAT 0
+    INT16_TO_FLOAT 1
+    INT16_TO_FLOAT 2
+    INT16_TO_FLOAT 3
+    vmulps       ymm1, ymm1, ymm0
+    vsubps       ymm4, ymm0, ymm3
+    vmulps       ymm1, ymm1, ymm6    ; intra*invq*fps_factor>>8
+    vaddps       ymm1, ymm1, ymm2    ; prop + (intra*invq*fps_factor>>8)
+    vrcpps       ymm3, ymm0          ; 1 / intra 1st approximation
+    vmulps       ymm2, ymm0, ymm3    ; intra * (1/intra 1st approx)
+    vmulps       ymm2, ymm2, ymm3    ; intra * (1/intra 1st approx)^2
+    vmulps       ymm1, ymm1, ymm4    ; (prop + (intra*invq*fps_factor>>8)) * (intra - inter)
+    vaddps       ymm3, ymm3, ymm3    ; 2 * (1/intra 1st approx)
+    vsubps       ymm3, ymm3, ymm2    ; 2nd approximation for 1/intra
+    vmulps       ymm1, ymm1, ymm3    ; / intra
+    vcvtps2dq    ymm1, ymm1
+    vmovdqu [r0+r6*2], ymm1
+    add            r6, 16
+    jl .loop
+    vzeroupper
+    RET
diff --git a/common/x86/mc-c.c b/common/x86/mc-c.c
index a789f96..408eb5e 100644
--- a/common/x86/mc-c.c
+++ b/common/x86/mc-c.c
@@ -140,6 +140,8 @@ void x264_integral_init8v_sse2( uint16_t *sum8, int stride );
 void x264_integral_init4v_ssse3( uint16_t *sum8, uint16_t *sum4, int stride );
 void x264_mbtree_propagate_cost_sse2( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
                                       uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len );
+void x264_mbtree_propagate_cost_avx( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
+                                     uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len );
 
 #define MC_CHROMA(cpu)\
 void x264_mc_chroma_##cpu( pixel *dstu, pixel *dstv, int i_dst,\
@@ -728,4 +730,8 @@ void x264_mc_init_mmx( int cpu, x264_mc_functions_t *pf )
     if( !(cpu&X264_CPU_STACK_MOD4) )
         pf->mc_chroma = x264_mc_chroma_avx;
 #endif // HIGH_BIT_DEPTH
+
+    if( !(cpu&X264_CPU_AVX) )
+        return;
+    pf->mbtree_propagate_cost = x264_mbtree_propagate_cost_avx;
 }
diff --git a/tools/checkasm.c b/tools/checkasm.c
index a0ae4fc..1a558b7 100644
--- a/tools/checkasm.c
+++ b/tools/checkasm.c
@@ -1255,8 +1255,8 @@ static int check_mc( int cpu_ref, int cpu_new )
             int *dstc = dsta+400;
             uint16_t *prop = (uint16_t*)buf1;
             uint16_t *intra = (uint16_t*)buf4;
-            uint16_t *inter = intra+100;
-            uint16_t *qscale = inter+100;
+            uint16_t *inter = intra+128;
+            uint16_t *qscale = inter+128;
             uint16_t *rnd = (uint16_t*)buf2;
             x264_emms();
             for( int j = 0; j < 100; j++ )



More information about the x264-devel mailing list