◎スプライトルーチン(その1)
ピクセルフォーマットは16bpp(I1R5G5B5)とします。
スプライトパターンのIビットが0の場合のみフレームバッファへ転送します。
/* C言語風表記(1ピクセル処理) */
/* vram = フレームバッファへのポインタ */
/* sprite = スプライトパターンへのポインタ */
*vram = (*sprite & 0x8000) ? *vram : *sprite;
; NASM(8ピクセル処理)
;UV大文字表記は他のパイプに移動できない命令です
;edi = フレームバッファのアドレス
;ebx = スプライトパターンのアドレス
movq mm1,[ebx] ;U1 mm1 = *sprite
pxor mm2,mm2 ;v1 mm2 = 0
movq mm4,[ebx+8] ;U2
pxor mm5,mm5 ;v2
movq mm0,[edi] ;U3 mm0 = *vram
pcmpgtw mm2,mm1 ;v3 mm2 = (0 > *sprite) ? 0xffff : 0
movq mm3,[edi+8] ;U4
pcmpgtw mm5,mm4 ;v4
psubw mm0,mm1 ;u5 mm0 = *vram - *sprite
psubw mm3,mm4 ;v5
pand mm0,mm2 ;u6 mm0 = (0 > *sprite) ? *vram - *sprite : 0
pand mm3,mm5 ;v6
lea edi,[edi+16] ;u7 パイプが空いたので入れてみる
paddw mm0,mm1 ;v7 mm0 = (0 > *sprite) ? *vram : *sprite
lea ebx,[ebx+16] ;u8 パイプが空いたので入れてみる
paddw mm3,mm4 ;v8
movq [edi-16],mm0 ;U9<-8 メモリストアは1クロック前に準備される
;v9 MMX命令のみ挿入可能
movq [edi-8],mm3 ;U10<-9
有効なペアリングのために4ピクセルのデーターを2組処理しています。
とりあえずキャッシュが全てヒットした場合を考えます。
MMX Pentium(P55C)では、
8ピクセル当たり10クロックで処理します。
パターンをQWORDにアラインするのは当然にしても、
転送先のアドレスは表示位置によって変わってしまうので、
8ピクセル当たり22クロック程度と考えるのが妥当です。
これらの値は実際に測定し確認しました。
実際の実行速度はメモリのキャッシュ状況に大きく依存しますので、
パターンの描画順序、メモリ配置等を十分に考慮する必要があります。
◎スプライトルーチン(その2)
ピクセルフォーマットは、双方とも15bpp(R5G5B5)とします。
パターンの全ビットが0の場合転送しません。
/* C言語風表記(1ピクセル処理) */
/* vram = フレームバッファへのポインタ */
/* sprite = スプライトパターンへのポインタ */
*vram = (*sprite == 0) ? *vram : *sprite;
; NASM(8ピクセル処理)
;UV大文字表記は他のパイプに移動できない命令です
;edi = フレームバッファのアドレス
;ebx = スプライトパターンのアドレス
movq mm1,[ebx] ;U1 mm1 = *sprite
pxor mm2,mm2 ;v1 mm2 = 0
movq mm4,[ebx+8] ;U2
pxor mm5,mm5 ;v2
movq mm0,[edi] ;U3 mm0 = *vram
pcmpeqw mm2,mm1 ;v3 mm2 = (0 == *sprite) ? 0xffff : 0
movq mm3,[edi+8] ;U4
pcmpeqw mm5,mm4 ;v4
psubw mm0,mm1 ;u5 mm0 = *vram - *sprite
psubw mm3,mm4 ;v5
pand mm0,mm2 ;u6 mm0 = (0 == *sprite) ? *vram - *sprite : 0
pand mm3,mm5 ;v6
lea edi,[edi+16] ;u7 パイプが空いたので入れてみる
paddw mm0,mm1 ;v7 mm0 = (0 == *sprite) ? *vram : *sprite
lea ebx,[ebx+16] ;u8 パイプが空いたので入れてみる
paddw mm3,mm4 ;v8
movq [edi-16],mm0 ;U9<-8
;v9 MMX命令のみ挿入可能
movq [edi-8],mm3 ;U10<-9
速度はスプライトルーチン(その1)と一緒です。
◎32bppスプライトルーチン
ピクセルフォーマットは32bpp(I8R8G8B8)とします。
スプライトパターンの全ビットが0の場合転送しません。
/* C言語風表記(1ピクセル処理) */
/* vram = フレームバッファへのポインタ */
/* sprite = スプライトパターンへのポインタ */
*vram = (*sprite == 0) ? *vram : *sprite;
; NASM整数命令版(1ピクセル処理)
;UV大文字表記は他のパイプに移動できない命令です
;edi = フレームバッファのアドレス
;ebx = スプライトパターンのアドレス
mov eax,[edi] ;u1
mov esi,[ebx] ;v1
mov edx,esi ;u2
add esi,-1 ;v2
sbb esi,esi ;U3
sub edx,eax ;v3
add edi,4 ;u4
and edx,esi ;v4
add ebx,4 ;u5
add eax,edx ;v5
mov [edi-4],eax ;u6
Pentium や MMX Pentium(P55C)では、
1ピクセル当たり6クロックで処理します。
パターンをDWORDにアラインするのは当然にしても、
転送先のアドレスは表示位置によって変わってしまうので、
1ピクセル当たり12クロック程度と考えるのが妥当です。
これらの値は実際に測定し確認しました。