现在的位置: 首页 > 综合 > 正文

16位Alpha混合的MMX优化

2013年09月12日 ⁄ 综合 ⁄ 共 2616字 ⁄ 字号 评论关闭
 

16位Alpha混合的MMX优化


  最近,我开始学习汇编程序,用来优化我的引擎,断断续续的学习了20多天,也有了一些心得体会,希望和他家一起分享:) 游戏中图形操作就是吃系统资源老虎,大量的cpu时钟都被他吃掉了,为了加速我的游戏引擎的图形处理速度,我对一些图形操作进行了汇编优化,并使用了威力惊人的MMX指令。为什么说威力惊人呢?看下去就明白了。

  MMX指令适合用来做大量的串操作,在MMX处理器中,提供了8个64位的寄存器,并且,MMX指令能够使用数据组的操作。所以,用来处理逐个点操作的图形处理最合适不过了。下面,我就用我的Alpha混合的代码来说明一下,MMX的强大处理能力:) 以前,我在主页上面写过一篇16位Alpha操作的文章,那个时候,我不会汇编,用C写的例子程序,在一个912X720的区域内Alpha混合的时候,FPS值只有3-4,实在是没有实用价值,现在,我手握MMX这个利剑,经过一番努力后,FPS值直线飙升,达到了14,整整有4倍的擦别啊!如果在640X480下面,全屏幕的alpha也能达到20多帧! 为什么有这么大的性能提升呢?开始我说过,mmx寄存器是64位的,分别是mm0--mm7一共八个。MMX的指令可以让mmx寄存器之间的运算按照byte,word,dword,qd分组运算。这就是问题的关键!让我们看看,我们的16位Alpha混合是一个点占用2个byte,在一个MMX寄存器中间,我们可以容纳4个这样的点,所以一次混合计算,将能够让四个点混合,这就是4倍速度提升的原因!!! 好,让我们看看实际的代码: 其中wdDest,wdRes分别是目的和源图形数据指针,__Depth使Alpha混合深度,值为0x0001000100010001 * nDepth,nMMXCount是我用来纪录一行进行多少次MMX操作的,Not_MMX_Point是拷贝矩形宽度除4的余数,因为一旦出现宽度不是4字节对齐,余下的多余点就必须按照普通的汇编代码处理了,这里,我值不过是留下了接口,没有去实现,因为寄存器不够用,需要push和pop。__Mask64为__int64类型的掩码,值为0x0001000100010001 * (short)m_nColorKey,__Mask是用来过滤多余颜色的奄码0x001f001f001f001f(因为图形为555格式)。 大家注意,每次都是用movq来移动4个点到mmx寄存器,然后实用word对齐分组计算的。 这里要说明,使用了mmx后,原来透明色是可以不处理的,现在必须处理,为了让透明部分不影响目的数据,我是用了一点小技巧,具体做法看我的代码注释。这可是我自己想出来的哦:) 要看完整的代码,请下载我的完整的JAppLib。

__asm
{
    //pusha;
    movq mm6,__Depth;
    mov eax,dword ptr wdDest;
    mov ebx,dword ptr wdRes;
    mov cx,nUseH;//纪录操作矩形高

Add_Next_Row:
    cmp cx,0;
    je All_End;
    xor dx,dx;

Next_MMX_Point:
    cmp dx,nMMXCount;
    je Not_MMX_Point;
    movq mm0,[eax];
    movq mm1,[ebx];
    movq mm7,mm1;
    pcmpeqw mm7,__Mask64;//这里用来处理透明色的,我的思路就是透明色就用目的颜色填充源
    psubusw mm1,mm7; //这样,透明部分目的和源一样,不管怎么去alpha,只要公式是正确的,
    pand mm7,mm0; //他们混合后的颜色就是不会变,add color特效也是同样的道理
    por mm1,mm7; //

    movq mm2,mm0;//g
    psrlw mm2,5;
    pand mm2,__Mask;
    movq mm3,mm1;
    psrlw mm3,5;
    pand mm3,__Mask;

    movq mm4,mm0;//r //wdDR=(((wdDR-wdRR)*nDepth+(wdRR<<5))>>5);
    psrlw mm4,10;
    pand mm4,__Mask;
    movq mm5,mm1;
    psrlw mm5,10;
    pand mm5,__Mask;

    //psllw mm0,1;//b
    pand mm0,__Mask;
    //psllw mm1,1;
    pand mm1,__Mask;

    psubsw mm0,mm1;
    pmullw mm0,mm6;
    psllw mm1,5;
    paddsw mm0,mm1;
    psrlw mm0,5;
    //psrlw mm0,5;
    //paddusw mm0,mm1;

    psubsw mm2,mm3;
    pmullw mm2,mm6;
    psllw mm3,5;
    paddsw mm2,mm3;
    psrlw mm2,5;
    //psrlw mm2,5;
    //paddusw mm2,mm3;

    psubsw mm4,mm5;
    pmullw mm4,mm6;
    psllw mm5,5;
    paddsw mm4,mm5;
    psrlw mm4,5;
    //psrlw mm4,5;
    //paddusw mm4,mm5;

    //psllw mm0,10;
    psllw mm2,5;
    psllw mm4,10;

    por mm0,mm2;
    por mm0,mm4;

    movq [eax],mm0;

    add eax,8;
    add ebx,8;
    inc dx;
    jmp Next_MMX_Point;

Not_MMX_Point:
    xor dx,dx;

Not_MMX_Next:
    cmp dx,nNotMMX;
    je Row_End;
    sub eax,2;
    sub ebx,2;
    inc dx;
    jmp Not_MMX_Next;

Row_End:
    sub eax,nUnUsed2;
    sub ebx,nUnUsed1;
    dec cx;
    jmp Add_Next_Row;
    //loop Add_Next_Row;

All_End:
    //popa;
    emms;
}

抱歉!评论已关闭.