Chiharu の日記

絵描き C/C++ プログラマーの日記です。

Parallel force - パラレル・フォース 〜ちょっと高速化。その 2

新しい PC はあれから安定して動作しているようです。SE-90PCI のアナログ出力は音がいいですね。デジタル出力のような音の硬さ (多分硬いほうが正確な波形なんでしょう) がなく、柔らかな音の広がりを感じます。その割りに解像感が落ちるわけでもなく。好みの音です。
ま、にわかオーディオ レビューはこのくらいにして、パラレル・フォースです。仕事で体調を崩してしまい、なかなか手が加えられていませんが、アルファ ブレンディングのコードを見直しました。
これまでは...

// 0-255 -> 0-256
inline const PixPacked convertRange255to256(const PixLevel iPixLevel)
{
  // return iAlpha * 256 / 255;
  return iPixLevel * 65794 / 65536;  // 0-255 → 0-256
}

除算をビットシフト化するため、上記のように 0-255 レンジを 0-256 レンジに変換できるようにして...

// Alpha blending
inline const PixPacked operator()(const PixPacked iDst, const PixPacked iSrc, const PixLevel iAlpha)
{
  const auto aSrcAlpha = convertRange255to256(iAlpha);
  const auto aDstAlpha = 256 - aSrcAlpha;
  const auto aDst13 = (((iDst & 0x00ff00ff) >> 0) * aDstAlpha + ((iSrc & 0x00ff00ff) >> 0) * aSrcAlpha) / 256;
  const auto aDst02 = (((iDst & 0xff00ff00) >> 8) * aDstAlpha + ((iSrc & 0xff00ff00) >> 8) * aSrcAlpha) / 256;
  return (aDst13 & 0xff00ff) | ((aDst02 & 0xff00ff) << 8);
}

上記のコードでアルファ ブレンディングしていました。画素の並びが XBGR という前提で、B+R と X+G をそれぞれまとめて計算しています。Pentium4 全盛期に PentiumII 用に書いたコードで、計測した当時はテーブル参照による最適化とどっこいでした。メモリ アクセスを伴わないため、今の CPU ではフュージョンやら高度なペアリングやらが働いて、テーブル参照よりも速いんじゃないかなー、とか思ってます。
しかし、改めて、よくよく見直してみると、画素の並びが XBGR なんだから X に相当する上位 8-bit は要らないなぁ、と思って、下記のように修正してみました。

// Alpha blending (2)
inline const PixPacked operator()(const PixPacked iDst, const PixPacked iSrc, const PixLevel iAlpha)
{
  const auto aSrcAlpha = convertRange255to256(iAlpha);
  const auto aDstAlpha = 256 - aSrcAlpha;
  const auto aDst13 = (iDst & 0xff00ff) * aDstAlpha + (iSrc & 0xff00ff) * aSrcAlpha;
  const auto aDst02 = (iDst & 0x00ff00) * aDstAlpha + (iSrc & 0x00ff00) * aSrcAlpha;
  return ((aDst13 & 0xff00ff00) | (aDst02 & 0x00ff0000)) >> 8;
}

このコードだと、上位 8-bit が捨てられてしまいますが、ビットシフトの回数が、4 回分減っています。aDst13 算出時の "/ 256" が 1 回、 aDst02 算出時の ">> 8" が 2 回、同じく "/ 256" が 1 回。事前に 1/256 しないことにより、return 文のビットシフトが逆を向いていますが、これはシフト回数差し引き 0 ですね。
この程度で最新の CPU での処理速度が上がるかどうか、修正時点では眉唾だったのですが、前回の最適化時点で 70fps だったものが、81fps にまで伸びました。んー。いまどきの CPU も結構単純なのね。SIMD 使えばこんな話ともおさらばなのですが、環境非依存のプリミティブな部分については、しばらく ANSI っぽいところでがんばりたいと思います。