<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Oct 25, 2013 at 7:25 AM, Min Chen <span dir="ltr"><<a href="mailto:chenm003@163.com" target="_blank">chenm003@163.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Min Chen <<a href="mailto:chenm003@163.com">chenm003@163.com</a>><br>
# Date 1382703678 -28800<br>
# Node ID 2221e3abb479b1e9a586d80d769373d13c7f7980<br>
# Parent 4ca4da7bdd36fbef00b9eefe54c0a56bf11633f3<br>
asm: interp_8tap_hv_pp_8x8() for InterpolateHV_8x8<br></blockquote><div><br></div><div>How does this compare, performance wise, to the combined h_ps + v_sp intrinsic functions?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/common/ipfilter.cpp<br>
--- a/source/common/ipfilter.cpp Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/common/ipfilter.cpp Fri Oct 25 20:21:18 2013 +0800<br>
@@ -401,6 +401,17 @@<br>
dst += dstStride;<br>
}<br>
}<br>
+typedef void (*ipfilter_ps_t)(pixel *src, intptr_t srcStride, short *dst, intptr_t dstStride, int width, int height, const short *coeff);<br>
+typedef void (*ipfilter_sp_t)(short *src, intptr_t srcStride, pixel *dst, intptr_t dstStride, int width, int height, const short *coeff);<br>
+<br>
+template<int N, int width, int height><br>
+void interp_hv_pp_c(pixel *src, intptr_t srcStride, pixel *dst, intptr_t dstStride, int idxX, int idxY)<br>
+{<br>
+ short m_immedVals[(64 + 8) * (64 + 8)];<br>
+ filterHorizontal_ps_c<N>(src - 3 * srcStride, srcStride, m_immedVals, width, width, height + 7, g_lumaFilter[idxX]);<br>
+ filterVertical_sp_c<N>(m_immedVals + 3 * width, width, dst, dstStride, width, height, g_lumaFilter[idxY]);<br>
+}<br></blockquote><div><br></div><div>the intermediate buffer should be an argument</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
}<br>
<br>
namespace x265 {<br>
@@ -411,7 +422,8 @@<br>
p.chroma_vpp[CHROMA_ ## W ## x ## H] = interp_vert_pp_c<4, W, H><br>
<br>
#define LUMA(W, H) \<br>
- p.luma_hpp[LUMA_ ## W ## x ## H] = interp_horiz_pp_c<8, W, H><br>
+ p.luma_hpp[LUMA_ ## W ## x ## H] = interp_horiz_pp_c<8, W, H>; \<br>
+ p.luma_hvpp[LUMA_ ## W ## x ## H] = interp_hv_pp_c<8, W, H><br>
<br>
void Setup_C_IPFilterPrimitives(EncoderPrimitives& p)<br>
{<br>
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/common/primitives.h<br>
--- a/source/common/primitives.h Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/common/primitives.h Fri Oct 25 20:21:18 2013 +0800<br>
@@ -199,6 +199,7 @@<br>
typedef void (*plane_copy_deinterleave_t)(pixel *dstu, intptr_t dstuStride, pixel *dstv, intptr_t dstvStride, pixel *src, intptr_t srcStride, int w, int h);<br>
<br>
typedef void (*filter_pp_t) (pixel *src, intptr_t srcStride, pixel *dst, intptr_t dstStride, int coeffIdx);<br>
+typedef void (*filter_hv_pp_t) (pixel *src, intptr_t srcStride, pixel *dst, intptr_t dstStride, int idxX, int idxY);<br>
<br>
/* Define a structure containing function pointers to optimized encoder<br>
* primitives. Each pointer can reference either an assembly routine,<br>
@@ -235,6 +236,7 @@<br>
filter_pp_t luma_hpp[NUM_LUMA_PARTITIONS];<br>
filter_pp_t chroma_vpp[NUM_CHROMA_PARTITIONS];<br>
filter_pp_t luma_vpp[NUM_LUMA_PARTITIONS];<br>
+ filter_hv_pp_t luma_hvpp[NUM_LUMA_PARTITIONS];<br>
<br>
intra_dc_t intra_pred_dc;<br>
intra_planar_t intra_pred_planar;<br>
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/common/x86/asm-primitives.cpp<br>
--- a/source/common/x86/asm-primitives.cpp Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/common/x86/asm-primitives.cpp Fri Oct 25 20:21:18 2013 +0800<br>
@@ -278,6 +278,8 @@<br>
p.sad_x4[LUMA_16x12] = x265_pixel_sad_x4_16x12_ssse3;<br>
p.sad_x3[LUMA_16x32] = x265_pixel_sad_x3_16x32_ssse3;<br>
p.sad_x4[LUMA_16x32] = x265_pixel_sad_x4_16x32_ssse3;<br>
+<br>
+ p.luma_hvpp[LUMA_8x8] = x265_interp_8tap_hv_pp_8x8_ssse3;<br>
}<br>
if (cpuMask & X265_CPU_SSE4)<br>
{<br>
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/common/x86/ipfilter8.asm<br>
--- a/source/common/x86/ipfilter8.asm Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/common/x86/ipfilter8.asm Fri Oct 25 20:21:18 2013 +0800<br>
@@ -35,7 +35,9 @@<br>
db 4, 5, 6, 7, 8, 9, 10, 11, 5, 6, 7, 8, 9, 10, 11, 12<br>
db 6, 7, 8, 9, 10, 11, 12, 13, 7, 8, 9, 10, 11, 12, 13, 14<br>
<br>
-tab_c_512: times 8 dw 512<br>
+tab_c_512: times 8 dw 512<br>
+tab_c_8192: times 8 dw 8192<br>
+tab_c_526336: times 4 dd 8192*64+2048<br>
<br>
tab_ChromaCoeff: db 0, 64, 0, 0<br>
db -2, 58, 10, -2<br>
@@ -51,6 +53,25 @@<br>
db -1, 4, -11, 40, 40, -11, 4, -1<br>
db 0, 1, -5, 17, 58, -10, 4, -1<br>
<br>
+tab_LumaCoeffV: times 4 dw 0, 0<br>
+ times 4 dw 0, 64<br>
+ times 4 dw 0, 0<br>
+ times 4 dw 0, 0<br>
+<br>
+ times 4 dw -1, 4<br>
+ times 4 dw -10, 58<br>
+ times 4 dw 17, -5<br>
+ times 4 dw 1, 0<br>
+<br>
+ times 4 dw -1, 4<br>
+ times 4 dw -11, 40<br>
+ times 4 dw 40, -11<br>
+ times 4 dw 4, -1<br>
+<br>
+ times 4 dw 0, 1<br>
+ times 4 dw -5, 17<br>
+ times 4 dw 58, -10<br>
+ times 4 dw 4, -1<br>
<br>
SECTION .text<br>
<br>
@@ -523,8 +544,8 @@<br>
pmaddubsw %1, %5<br>
phaddw %4, %1<br>
phaddw %2, %4<br>
+ %if %0 == 8<br>
pmulhrsw %2, %6<br>
- %if %0 == 8<br>
packuswb %2, %2<br>
movh %8, %2<br>
%endif<br>
@@ -623,3 +644,135 @@<br>
IPFILTER_LUMA 48, 64<br>
IPFILTER_LUMA 64, 16<br>
IPFILTER_LUMA 16, 64<br>
+<br>
+<br>
+;-----------------------------------------------------------------------------<br>
+; Interpolate HV<br>
+;-----------------------------------------------------------------------------<br>
+%macro FILTER_HV8_START 7 ; (t0, t1, t2, t3, t4, off_src, off_coeff) -> (t3, t5), (t4, t1), [2]<br>
+ mova %5, [r0 + (%6 + 0) * 16]<br>
+ mova %1, [r0 + (%6 + 1) * 16]<br>
+ mova %2, [r0 + (%6 + 2) * 16]<br>
+ punpcklwd %3, %5, %1<br>
+ punpckhwd %5, %1<br>
+ pmaddwd %3, [r5 + (%7) * 16] ; R3 = L[0+1] -- Row 0<br>
+ pmaddwd %5, [r5 + (%7) * 16] ; R0 = H[0+1]<br>
+ punpcklwd %4, %1, %2<br>
+ punpckhwd %1, %2<br>
+ pmaddwd %4, [r5 + (%7) * 16] ; R4 = L[1+2] -- Row 1<br>
+ pmaddwd %1, [r5 + (%7) * 16] ; R1 = H[1+2]<br>
+%endmacro ; FILTER_HV8_START<br>
+<br>
+%macro FILTER_HV8_MID 10 ; (Row3, prevRow, sum0L, sum1L, sum0H, sum1H, t6, t7, off_src, off_coeff) -> [6]<br>
+ mova %8, [r0 + (%9 + 0) * 16]<br>
+ mova %1, [r0 + (%9 + 1) * 16]<br>
+ punpcklwd %7, %2, %8<br>
+ punpckhwd %2, %8<br>
+ pmaddwd %7, [r5 + %10 * 16]<br>
+ pmaddwd %2, [r5 + %10 * 16]<br>
+ paddd %3, %7 ; R3 = L[0+1+2+3] -- Row 0<br>
+ paddd %5, %2 ; R0 = H[0+1+2+3]<br>
+ punpcklwd %7, %8, %1<br>
+ punpckhwd %8, %1<br>
+ pmaddwd %7, [r5 + %10 * 16]<br>
+ pmaddwd %8, [r5 + %10 * 16]<br>
+ paddd %4, %7 ; R4 = L[1+2+3+4] -- Row 1<br>
+ paddd %6, %8 ; R1 = H[1+2+3+4]<br>
+%endmacro ; FILTER_HV8_START<br>
+<br>
+; Round and Saturate<br>
+%macro FILTER_HV8_END 4 ; output in [1, 3]<br>
+ paddd %1, [tab_c_526336]<br>
+ paddd %2, [tab_c_526336]<br>
+ paddd %3, [tab_c_526336]<br>
+ paddd %4, [tab_c_526336]<br>
+ psrad %1, 12<br>
+ psrad %2, 12<br>
+ psrad %3, 12<br>
+ psrad %4, 12<br>
+ packssdw %1, %2<br>
+ packssdw %3, %4<br>
+<br>
+ ; TODO: is merge better? I think this way is short dependency link<br>
+ packuswb %1, %1<br>
+ packuswb %3, %3<br>
+%endmacro ; FILTER_HV8_END<br>
+<br>
+;-----------------------------------------------------------------------------<br>
+; void interp_8tap_hv_pp_%1x%2(pixel *src, intptr_t srcStride, pixel *dst, intptr_t dstStride, int idxX, int idxY)<br>
+;-----------------------------------------------------------------------------<br>
+INIT_XMM ssse3<br>
+cglobal interp_8tap_hv_pp_8x8, 4, 7, 8, 0-15*16<br>
+%define coef m7<br>
+%define stk_buf rsp<br>
+<br>
+ mov r4d, r4m<br>
+ mov r5d, r5m<br>
+<br>
+%ifdef PIC<br>
+ lea r6, [tab_LumaCoeff]<br>
+ movh coef, [r6 + r4 * 8]<br>
+%else<br>
+ movh coef, [tab_LumaCoeff + r4 * 8]<br>
+%endif<br>
+ punpcklqdq coef, coef<br>
+<br>
+; FILTER_H8_W8 7-8 ; t0, t1, t2, t3, coef, c512, src, dst<br>
+<br>
+ ; move to row -3<br>
+ lea r6, [r1 + r1 * 2]<br>
+ sub r0, r6<br>
+<br>
+ xor r6, r6<br>
+ mov r4, rsp<br>
+<br>
+.loopH:<br>
+ FILTER_H8_W8 m0, m1, m2, m3, coef, [tab_c_512], [r0 - 3]<br>
+ psubw m1, [tab_c_8192]<br>
+ mova [r4], m1<br>
+<br>
+ add r0, r1<br>
+ add r4, 16<br>
+ inc r6<br>
+ cmp r6, 8+7<br>
+ jnz .loopH<br>
+<br>
+ ; ready to phase V<br>
+ ; Here all of mN is free<br>
+<br>
+ ; load coeff table<br>
+ shl r5, 6<br>
+ lea r6, [tab_LumaCoeffV]<br>
+ lea r5, [r5 + r6]<br>
+<br>
+ ; load intermedia buffer<br>
+ mov r0, stk_buf<br>
+<br>
+ ; register mapping<br>
+ ; r0 - src<br>
+ ; r5 - coeff<br>
+ ; r6 - loop_i<br>
+<br>
+ ; let's go<br>
+ xor r6, r6<br>
+<br>
+ ; TODO: this loop have more than 70 instructions, I think it is more than Intel loop decode cache<br>
+.loopV:<br>
+<br>
+ FILTER_HV8_START m1, m2, m3, m4, m0, 0, 0<br>
+ FILTER_HV8_MID m6, m2, m3, m4, m0, m1, m7, m5, 3, 1<br>
+ FILTER_HV8_MID m5, m6, m3, m4, m0, m1, m7, m2, 5, 2<br>
+ FILTER_HV8_MID m6, m5, m3, m4, m0, m1, m7, m2, 7, 3<br>
+ FILTER_HV8_END m3, m0, m4, m1<br>
+<br>
+ movq [r2], m3<br>
+ movq [r2 + r3], m4<br>
+<br>
+ lea r0, [r0 + 16 * 2]<br>
+ lea r2, [r2 + r3 * 2]<br>
+<br>
+ inc r6<br>
+ cmp r6, 8/2<br>
+ jnz .loopV<br>
+<br>
+ RET<br>
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/common/x86/ipfilter8.h<br>
--- a/source/common/x86/ipfilter8.h Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/common/x86/ipfilter8.h Fri Oct 25 20:21:18 2013 +0800<br>
@@ -87,6 +87,8 @@<br>
CHROMA_FILTERS(_sse4);<br>
LUMA_FILTERS(_sse4);<br>
<br>
+void x265_interp_8tap_hv_pp_8x8_ssse3(pixel * src, intptr_t srcStride, pixel * dst, intptr_t dstStride, int idxX, int idxY);<br>
+<br>
#undef SETUP_CHROMA_FUNC_DEF<br>
#undef SETUP_LUMA_FUNC_DEF<br>
#undef CHROMA_FILTERS<br>
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/test/ipfilterharness.cpp<br>
--- a/source/test/ipfilterharness.cpp Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/test/ipfilterharness.cpp Fri Oct 25 20:21:18 2013 +0800<br>
@@ -325,6 +325,40 @@<br>
return true;<br>
}<br>
<br>
+bool IPFilterHarness::check_IPFilterLumaHV_primitive(filter_hv_pp_t ref, filter_hv_pp_t opt)<br>
+{<br>
+ int rand_srcStride, rand_dstStride, rand_coeffIdxX, rand_coeffIdxY;<br>
+<br>
+ for (int i = 0; i <= 1000; i++)<br>
+ {<br>
+ rand_coeffIdxX = rand() % 3; // Random coeffIdex in the filter<br>
+ rand_coeffIdxY = rand() % 3; // Random coeffIdex in the filter<br>
+<br>
+ rand_srcStride = rand() % 100; // Randomly generated srcStride<br>
+ rand_dstStride = rand() % 100; // Randomly generated dstStride<br>
+<br>
+ ref(pixel_buff + 3 * rand_srcStride,<br>
+ rand_srcStride,<br>
+ IPF_C_output_p,<br>
+ rand_dstStride,<br>
+ rand_coeffIdxX,<br>
+ rand_coeffIdxY<br>
+ );<br>
+ opt(pixel_buff + 3 * rand_srcStride,<br>
+ rand_srcStride,<br>
+ IPF_vec_output_p,<br>
+ rand_dstStride,<br>
+ rand_coeffIdxX,<br>
+ rand_coeffIdxY<br>
+ );<br>
+<br>
+ if (memcmp(IPF_vec_output_p, IPF_C_output_p, ipf_t_size))<br>
+ return false;<br>
+ }<br>
+<br>
+ return true;<br>
+}<br>
+<br>
bool IPFilterHarness::testCorrectness(const EncoderPrimitives& ref, const EncoderPrimitives& opt)<br>
{<br>
for (int value = 0; value < NUM_IPFILTER_P_P; value++)<br>
@@ -421,6 +455,18 @@<br>
}<br>
}<br>
<br>
+ for (int value = 0; value < NUM_LUMA_PARTITIONS; value++)<br>
+ {<br>
+ if (opt.luma_hvpp[value])<br>
+ {<br>
+ if (!check_IPFilterLumaHV_primitive(ref.luma_hvpp[value], opt.luma_hvpp[value]))<br>
+ {<br>
+ printf("luma_hvpp[%s]", lumaPartStr[value]);<br>
+ return false;<br>
+ }<br>
+ }<br>
+ }<br>
+<br></blockquote><div><br></div><div>You can merge this with the existing loop over luma partition sizes.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
return true;<br>
}<br>
<br>
@@ -486,6 +532,7 @@<br>
REPORT_SPEEDUP(opt.luma_hpp[value], ref.luma_hpp[value],<br>
pixel_buff + srcStride, srcStride, IPF_vec_output_p, dstStride, 1);<br>
}<br>
+<br>
if (opt.luma_vpp[value])<br>
{<br>
printf("luma_vpp[%s]\t", lumaPartStr[value]);<br>
@@ -493,6 +540,13 @@<br>
pixel_buff + maxVerticalfilterHalfDistance * srcStride, srcStride,<br>
IPF_vec_output_p, dstStride, 1);<br>
}<br>
+<br>
+ if (opt.luma_hvpp[value])<br>
+ {<br>
+ printf("luma_hv [%s]\t", lumaPartStr[value]);<br>
+ REPORT_SPEEDUP(opt.luma_hvpp[value], ref.luma_hvpp[value],<br>
+ pixel_buff + srcStride, srcStride, IPF_vec_output_p, dstStride, 1, 3);<br>
+ }<br>
}<br>
<br>
for (int value = 0; value < NUM_CHROMA_PARTITIONS; value++)<br>
diff -r 4ca4da7bdd36 -r 2221e3abb479 source/test/ipfilterharness.h<br>
--- a/source/test/ipfilterharness.h Fri Oct 25 12:11:31 2013 +0530<br>
+++ b/source/test/ipfilterharness.h Fri Oct 25 20:21:18 2013 +0800<br>
@@ -48,6 +48,7 @@<br>
bool check_IPFilter_primitive(ipfilter_s2p_t ref, ipfilter_s2p_t opt);<br>
bool check_IPFilterChroma_primitive(filter_pp_t ref, filter_pp_t opt);<br>
bool check_IPFilterLuma_primitive(filter_pp_t ref, filter_pp_t opt);<br>
+ bool check_IPFilterLumaHV_primitive(filter_hv_pp_t ref, filter_hv_pp_t opt);<br>
<br>
public:<br>
<br>
<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Steve Borho
</div></div>