2001-08-16 (木)
-
天気:曇り
*MMXで最適化
昨日,MMX化をした部分を最適かできないか見直してみました.まだ,ちょっと高速化できそうです.
movd mm0, [eax] movd mm1, [ebx] punpcklbw mm0, mm3 punpcklbw mm1, mm3 pmullw mm0, mm4 // *=α pmullw mm1, mm5 // *=(255-α) psrlw mm0, 8 // >>=8 psrlw mm1, 8 // >>=8 paddusw mm0, mm1 // +=mm1 packuswb mm0, mm3 movd [edx], mm0
半透明合成用のループの中が上のようになってます.こうすると,Pentiumなら2命令ずつ同時に実行されるみたいですね.加算の後にシフトした方がコードのサイズが小さくなる分いい気がします.あとは,まだMMXレジスタが余ってるので,64ビットずつ処理した方がよさそうです.
void alpha_brend(BMSCR* des,BMSCR* src1, BMSCR* src2, int alpha)
{
DWORD *d,*s1,*s2;
DWORD alpha2;
int siz=(des->sx*3*des->sy)&rt;&rt;3;
d=(DWORD*)des->pBit;
s1=(DWORD*)src1->pBit;
s2=(DWORD*)src2->pBit;
alpha*=0x01010101;
alpha2=~alpha;
_asm{
mov eax, s1
mov ebx, s2
mov edx, d
mov ecx,siz //ループ用
pxor mm3, mm3
movd mm4, alpha2
movd mm5, alpha
punpcklbw mm4, mm3
punpcklbw mm5, mm3
alpha_loop:
//読む
movq mm0, [eax]
movq mm1, [ebx]
//コピー
movq mm6, mm0
movq mm7, mm1
//下位32bit
punpcklbw mm0, mm3
punpcklbw mm1, mm3
pmullw mm0, mm4
pmullw mm1, mm5
paddusw mm0, mm1
psrlw mm0, 8
//上位32bit
punpckhbw mm6, mm3
punpckhbw mm7, mm3
pmullw mm6, mm4
pmullw mm7, mm5
paddusw mm6, mm7
psrlw mm6, 8
//書く
packuswb mm0, mm6
movq [edx], mm0
add eax,8
add ebx,8
add edx,8
loop alpha_loop
emms//END MMX
}
}
出来上がったのがこれ.一応,Celeron500MHzで640*480*24ビット画像を(表示なしで)65FPSくらいで処理できてます.ちょっと長くなったけど,コンパイル後のコードは200バイト未満だし,そんなでもないだろう….まだ,最適化の余地があるかもしれませんが…例えば,加算後のシフトは別の場所でやればペアリング出来て同時に処理できる気もします….最適化ってはまると抜け出せなくなります(爆).α合成くらい,その辺のサンプルもってくれば手っ取り早そうですが,とりあえず,MMXの勉強ということで(^^;それにしても暫く見ない間にずいぶん便利になってますね.アセンブラには手を出さないつもりでいましたが,このくらいなら楽に高速化できて良いですね(^^;.