Nanashi-softプログラマ専用Windows gcc SDL


◇Windowsでgcc+SDL -SSE2(SIMD)で半透明処理する-

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]);

のように書くのが正解ですね


TOPプログラマ専用Windows gcc SDL