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]);
のように書くのが正解ですね