私が変換しているゲームは8ビットのパレットテクスチャで動作しており、レンダリングのためにそのテクスチャの一部をOpenGLテクスチャに更新する必要があるほぼすべてのフレームです。次のようになります。
unsigned short RGB565PaletteLookupTable[256]; // Lookup table
unsigned char* Src; // Source data
unsigned short* Dst; // Destination buffer
int SrcPitch; // Source data row length
int OriginX, OriginY, Width, Height; // Subrectangle to copy
assert( Width % 4 == 0 );
int SrcOffset = SrcPitch-Width;
Src += OriginY*SrcPitch+OriginX;
int x, y;
for( y = OriginY; y < OriginY+Height; ++y, Src += SrcOffset )
{
for( x = OriginX; x < OriginX+Width; x += 4 )
{
*Dst++ = RGB565PaletteLookupTable[*Src++];
*Dst++ = RGB565PaletteLookupTable[*Src++];
*Dst++ = RGB565PaletteLookupTable[*Src++];
*Dst++ = RGB565PaletteLookupTable[*Src++];
}
}
このコードはゲーム中にメインスレッド時間の17%を要するので、私はそれをスピードアップする方法を探しています。データは直接glTexSubImage2D()に送られるため、宛先バッファーでは何も変更できません。それは古くて文書化されていないゲームのコードから来ており、それがどのように機能するかはもう誰にもわからないので、私もそれをあまり混乱させることはできません。ルックアップテーブルはこの古代のコードによっても提供され、ゲーム中に変更される可能性があります。
Accelerateフレームワーク/アセンブリ命令/その他の手段を使用してこのコードを高速化することは可能でしょうか?RGB888からRGB565への直接変換の例を読みましたが、これらはルックアップテーブルを使用する必要はありませんでした。それを最適にスピードアップする方法を学ぶためにどこを見ればよいですか?
更新:OriginXも4整列であり、次のようにコードを改良できたことがわかりました。
unsigned long RGB565PaletteLookupTable[256]; // Lookup table
unsigned char* Src; // Source data
unsigned long* Dst; // Destination buffer
int SrcPitch; // Source data row length
int OriginX, OriginY, Width, Height; // Subrectangle to copy
assert( Width % 4 == 0 );
int SrcOffset = SrcPitch-Width;
Src += OriginY*SrcPitch+OriginX;
SrcOffset >>= 2;
int x, y;
unsigned long* LSrc = (unsigned long*)Src;
for( y = OriginY; y < OriginY+Height; ++y, LSrc += SrcOffset )
{
for( x = OriginX; x < OriginX+Width; x += 4 )
{
unsigned long Indexes = *LSrc++;
unsigned long Result = RGB565PaletteLookupTable[ Indexes & 0xFF ];
Indexes >>= 8;
Result |= ( RGB565PaletteLookupTable[ Indexes & 0xFF ] << 16 );
*Dst++ = Result;
Indexes >>= 8;
Result = RGB565PaletteLookupTable[ Indexes & 0xFF ];
Indexes >>= 8;
Result |= ( RGB565PaletteLookupTable[ Indexes & 0xFF ] << 16 );
*Dst++ = Result;
}
}
このコードは、私が知る限りではありません。アラインされていないメモリアクセスを使用します。パフォーマンスが少し向上しました。つまり、メインスレッド時間の15.5%が必要になります。でももっとスピードアップしたいと思っていました。
理論的には、ルックアップテーブルの操作はそれぞれ、前の操作と後続の操作から独立しているため(それぞれが同じルックアップテーブルから読み取るという事実は別として)、SIMD命令、またはおそらくアセンブリ命令があると予想していました。これにより、多くのピクセルを並行して検索できます。何かのようなもの
_mm_movemask_ps( _mm_cmpneq_ps( _mm_loadu_ps( cmp1 ), _mm_loadu_ps( cmp2 ) ) ) )
Macではmemcmp(cmp1、cmp2、16)と同じことをしますが、8倍速くなります。
私は今それを探し続けます。
更新:NEON命令セットを使用してテーブルルックアップを高速化する方法はないようだと判断しました。テーブルは512バイトの大きさである必要があり、ARMレジスタに完全に収める方法はありません。VTBXNEON命令は一度に最大32バイトを処理でき、ルックアップ結果のサイズは次のサイズと等しくなければならないことも前提としています。インデックス。http://forums.arm.com/index.php?/topic/15521-8bit-look-up-table-by-neon-code/で説明されている同様の問題の解決策として解決できる可能性のあるものがありますが、それは勝ちました私には合いません。したがって、すべてのオペランドの配置が正しいことを確認することが、この問題に対する最善の答えのようです。