Nanashi-soft○プログラマ専用○Windows gcc SDL○
PS3 Linuxの時に行った事と同じ事をやってみます
グラフィックの一部に半透明な四角を描く例です
SIMD向けロジックに変更したプログラムは以下のものでした
for(y=0; y < 480; y++){
for(x=0; x < 640; x++){
int r, g, b;
r = rgbdata[y*1920*3 + x*3];
g = rgbdata[y*1920*3 + x*3 +1];
b = rgbdata[y*1920*3 + x*3 +2];
r = r + 255;
g = g + 255;
b = b + 0;
r = r >> 1;
g = g >> 1;
b = b >> 1;
}
}
これを SSE2でプログラミングしてみます
for(y=0; y < 480; y++){
for(x=0; x < 640; x++){
__m128i vrgb; //vector変数を宣言
vrgb= _mm_set_epi32(rgbdata[y*1920*3 + x*3], rgbdata[y*1920*3 + x*3 +1], rgbdata[y*1920*3 + x*3 +2], 0); //ベクタ変数にセット、残りは0で埋めておく
//+255の足し算
__m128i vplus;
vplus= _mm_set_epi32(255, 255, 0, 0);
vrgb= _mm_add_epi32(vrgb, vplus);
//右シフト演算
vrgb= _mm_srli_epi32(vrgb, 1);
//元の変数に戻す
vrgb= _mm_srli_si128(vrgb, 4);
rgbdata[y*1920*3 + x*3 +2] = _mm_cvtsi128_si32(vc);
vrgb= _mm_srli_si128(vrgb, 4);
rgbdata[y*1920*3 + x*3 +1] = _mm_cvtsi128_si32(vc);
vrgb= _mm_srli_si128(vrgb, 4);
rgbdata[y*1920*3 + x*3] = _mm_cvtsi128_si32(vc);
}
}
注意点として、値を取り出すのは下位バイトからです
CPUを限定してしまうかも知れませんが、無理やりint型にキャストする方法もあります
//元の変数に戻す
int *pvrgb = (int*)&vrgb; //vector変数のポインタ取得
rgbdata[y*1920*3 + x*3] = pvrgb[3];
rgbdata[y*1920*3 + x*3 +1] = pvrgb[2];
rgbdata[y*1920*3 + x*3 +2] = pvrgb[1];
でもやっぱり反対に入っています(謎
上下反対のエンディアン問題と異なり、全体が反転しています
_mm_set_epi32が反対に入れている事が原因のようです
つまり
vrgb= _mm_set_epi32(rgbdata[y*1920*3 + x*3], rgbdata[y*1920*3 + x*3 +1], rgbdata[y*1920*3 + x*3 +2], 0); //ベクタ変数にセット、残りは0で埋めておく
は、
vrgb= _mm_set_epi32(0, rgbdata[y*1920*3 + x*3 +2], rgbdata[y*1920*3 + x*3 +1], rgbdata[y*1920*3 + x*3]);
のように書くのが正解ですね