2011/07/24
OpenGL/DirectX のピクセル並びの順番
OpenGL と DirectX は色の並び順が異なります。
●OpenGL の場合
OpenGL はメモリのアクセス単位が TYPE で決まっています。
例えば GL_UNSIGNED_BYTE の場合バイトオーダーに関係なくメモリの並びは
一定となります。
・OpenGL はメモリ上の配列は R G B A の順。
・short 等パックされた場合は上位 bit から R G B A。アルファが最下位。
メモリの並びとパックされた値は Big endian (BE) の場合に一致します。
R G B A の順番は X Y Z W の対応と等しく、float (fp16/32) 等のフォーマット
時の並びと一致します。
●DirectX の場合
アクセス単位という概念が特に無く 32bit/16bit 共に違いを意識しません。
・int/short 等パックされた場合、最上位がアルファ。上位から A R G B の順。
・メモリ上の配列は 32/24bit を LE で格納するため B G R A の順になる。
Little endian (LE) で格納した場合 24bit color と 32bit color の構造に
互換性があります。(B G R X → B G R A)
GL と D3D の違いはフォーマット作成時の GE と LE の違いかもしれません。
ARGB の順番 (D3DCOLOR) は XYZW と一致しません。
常に XYZW 順である float (fp16/32) フォーマットとも異なっています。
Direct3D10 では RGBA 並びをもとに大きく変更されました。
Direct3D9 以前と Direct3D10 (DXGI) 以降では FORMAT シンボルの表記順も
逆になっています。
●相互変換
OpenGL で dds を用いたり、モバイルの OpenGL ES と PC の DirectX で
エンジンを共通化する場合はこれらの画素変換が必要になります。
具体例
・OpenGLES2.0 DDS テクスチャを読み込む
モバイル GPU ではバス帯域がボトルネックになりがちです。
出来る限り圧縮テクスチャを用いますが、未対応 GPU の場合は
16bit テクスチャを活用することになります。
関連エントリ
・Android OpenGL ES 2.0 の圧縮テクスチャ
・OpenGLES2.0 DDS テクスチャを読み込む
GL Type OpenGL DirectX9 ------------------------------------------------------------ 8888 BYTE R8G8B8A8 B8G8R8A8 (A8R8G8B8) 888 BYTE R8G8B8 B8G8R8 (R8G8B8) 565 SHORT R5G6B5 R5G6B5 5551 SHORT R5G5B5A1 A1R5G5B5 4444 SHORT R4G4B4A4 A4R4G4B4 HALF HALF R16G16B16A16F R16G16B16A16F (A16B16G16R16F) FLOAT FLOAT R32G32B32A32F R32G32B32A32F (A32B32G32R32F) OpenGL(LE) OpenGL(BE) DirectX9(LE) ----------------------------------------------------------------- 1byte目 2byte目 1byte目 2byte目 1byte目 2byte目 H______L H______L H______L H______L H______L H______L 565 gggbbbbb rrrrrggg rrrrrggg gggbbbbb gggbbbbb rrrrrggg 5551 ggbbbbba rrrrrggg rrrrrggg ggbbbbba gggbbbbb arrrrrgg 4444 bbbbaaaa rrrrgggg rrrrgggg bbbbaaaa ggggbbbb aaaarrrr Alpha 位置の違いなので 565 は OpenGL/DirectX どちらも同じ。
●OpenGL の場合
OpenGL はメモリのアクセス単位が TYPE で決まっています。
例えば GL_UNSIGNED_BYTE の場合バイトオーダーに関係なくメモリの並びは
一定となります。
・OpenGL はメモリ上の配列は R G B A の順。
・short 等パックされた場合は上位 bit から R G B A。アルファが最下位。
メモリの並びとパックされた値は Big endian (BE) の場合に一致します。
R G B A の順番は X Y Z W の対応と等しく、float (fp16/32) 等のフォーマット
時の並びと一致します。
●DirectX の場合
アクセス単位という概念が特に無く 32bit/16bit 共に違いを意識しません。
・int/short 等パックされた場合、最上位がアルファ。上位から A R G B の順。
・メモリ上の配列は 32/24bit を LE で格納するため B G R A の順になる。
Little endian (LE) で格納した場合 24bit color と 32bit color の構造に
互換性があります。(B G R X → B G R A)
GL と D3D の違いはフォーマット作成時の GE と LE の違いかもしれません。
ARGB の順番 (D3DCOLOR) は XYZW と一致しません。
常に XYZW 順である float (fp16/32) フォーマットとも異なっています。
Direct3D10 では RGBA 並びをもとに大きく変更されました。
Direct3D9 以前と Direct3D10 (DXGI) 以降では FORMAT シンボルの表記順も
逆になっています。
Direct3D9 ABGR順 D3DFMT_A16B16G16R16F Direct3D10/11(DXGI) RGBA順 DXGI_FORMAT_R16G16B16A16_FLOAT
●相互変換
OpenGL で dds を用いたり、モバイルの OpenGL ES と PC の DirectX で
エンジンを共通化する場合はこれらの画素変換が必要になります。
具体例
・OpenGLES2.0 DDS テクスチャを読み込む
モバイル GPU ではバス帯域がボトルネックになりがちです。
出来る限り圧縮テクスチャを用いますが、未対応 GPU の場合は
16bit テクスチャを活用することになります。
関連エントリ
・Android OpenGL ES 2.0 の圧縮テクスチャ
・OpenGLES2.0 DDS テクスチャを読み込む
2011/07/15
ARM cpu vfp の種類と fp16 命令を使ってみる
ARMv7 の fpu、vfp には大きく分けて NEON 命令のありなしで 2種類あります。
細かい違いを含めると更に増えます。
gcc のオプションを見るとこんな感じ。
使える機能はハードウエアレジスタ MVFR0/MVFR1 を見ることで判断できる
ようです。分かる範囲でまとめてみました。
・ARM vfp の種類
Cortex-A9 以降は fp16 (16bit 浮動小数点命令) に対応しています。
vfpv3 と vfpv4 の違いは FMA (Fused Multiply Add) にあるようです。
また VFP の Vector Mode (SV) が Cortex-A9 の NEON 版から無くなっている
こともわかります。この場合 FPSCR の Len が 0 以外の場合例外が発生し、
ソフトウエアでエミュレーションすることになるようです。
Cortex-A9 で fp16 命令を試してみました。
下記の命令で 16bit, 32bit float の相互変換ができます。
Android NDK ではオプション指定してもコンパイルできませんでしたが、
iOS ではコンパイルが通りました。
iPad2 (Cortex-A9) で動作し、相互変換できました。
fp16 未対応の iPod touch 3 (Cortex-A8) ではエラーで停止します。
・Mobile GPU の比較
PowerVR SGX, Adreno, Tegra2 など 16bit (half) float 対応の GPU は
意外に多いので、頂点フォーマットの変換に使いたい機能です。
関連エントリ
・Snapdragon の本当の浮動小数点演算能力
・iPad2 A5 と浮動小数演算 VFP/NEON
・Tegra2 Cortex-A9 と浮動小数演算
・Snapdragon と浮動小数演算速度
・ARM Cortex-A8 の NEON と浮動小数演算最適化
細かい違いを含めると更に増えます。
gcc のオプションを見るとこんな感じ。
vfp vfpv3 vfpv3-d16 vfpv3-fp16 vfpv3-d16-fp16 neon neon-fp16 vfpv4 vfpv4-d16 neon-vfpv4
使える機能はハードウエアレジスタ MVFR0/MVFR1 を見ることで判断できる
ようです。分かる範囲でまとめてみました。
・ARM vfp の種類
D32 VSP VDP DIV SQR SV NLS NI NSP NHP VHP FMA -------------------------------------------------------------------- Cortex-A8 vfpv3+NEON ◎ ◎ ◎ ◎ ◎ ◎ ◎ ◎ ◎ -- -- -- Cortex-A9 vfpv3-D16 -- ◎ ◎ ◎ ◎ ◎ -- -- -- -- ◎ -- Cortex-A9 vfpv3+NEON ◎ ◎ ◎ ◎ ◎ -- ◎ ◎ ◎ ◎ ◎ -- Cortex-A5 vfpv4-D16 -- ◎ ◎ ◎ ◎ -- - -- -- - ◎ ◎ Cortex-A5 vfpv4+NEON ◎ ◎ ◎ ◎ ◎ -- ◎ ◎ ◎ ◎ ◎ ◎ -------------------------------------------------------------------- D32 = double 32個 VSP = VFP 単精度演算 VDP = VFP 倍精度演算 DIV = HW 除算 SQR = HW 平方根 SV = VFP Short Vector 対応 NLS = NEON Load/Store NI = NEON Int演算 NSP = NEON 単精度演算 NHP = NEON half(fp16) 演算 VHP = VFP half(fp16) 演算 FMA = IEEE 積和 Fused Multiply Add
Cortex-A9 以降は fp16 (16bit 浮動小数点命令) に対応しています。
vfpv3 と vfpv4 の違いは FMA (Fused Multiply Add) にあるようです。
また VFP の Vector Mode (SV) が Cortex-A9 の NEON 版から無くなっている
こともわかります。この場合 FPSCR の Len が 0 以外の場合例外が発生し、
ソフトウエアでエミュレーションすることになるようです。
Cortex-A9 で fp16 命令を試してみました。
下記の命令で 16bit, 32bit float の相互変換ができます。
vcvtb.f16.f32 sd, ss vcvtt.f16.f32 sd, ss vcvtb.f32.f16 sd, ss vcvtt.f32.f16 sd, ss
Android NDK ではオプション指定してもコンパイルできませんでしたが、
iOS ではコンパイルが通りました。
unsigned int SingleToHalf( float a, float b ) { float fparam[4]; fparam[0]= a; fparam[1]= b; __asm__ __volatile__( "vldmia %0, {d0-d1}\n" "vcvtb.f16.f32 s2, s0\n" "vcvtt.f16.f32 s2, s1\n" "vstmia %0, {d0-d1}\n" : "=&r"( fparam ) : "0"( fparam ) : "d0","d1","cc" ); unsigned int* iparam= (unsigned int*)fparam; return iparam[2]; } void HalfToSingle( unsigned int param_in ) { unsigned int iparam[4]; iparam[0]= param_in; __asm__ __volatile__( "vldmia %0, {d0-d1}\n" "vcvtb.f32.f16 s1, s0\n" "vcvtt.f32.f16 s2, s0\n" "vstmia %0, {d0-d1}\n" : "=&r"( iparam ) : "0"( iparam ) : "d0","d1","cc" ); float* fparam= (float*)iparam; printf( "%f %f\n", fparam[0], fparam[1] ); }
iPad2 (Cortex-A9) で動作し、相互変換できました。
fp16 未対応の iPod touch 3 (Cortex-A8) ではエラーで停止します。
・Mobile GPU の比較
PowerVR SGX, Adreno, Tegra2 など 16bit (half) float 対応の GPU は
意外に多いので、頂点フォーマットの変換に使いたい機能です。
関連エントリ
・Snapdragon の本当の浮動小数点演算能力
・iPad2 A5 と浮動小数演算 VFP/NEON
・Tegra2 Cortex-A9 と浮動小数演算
・Snapdragon と浮動小数演算速度
・ARM Cortex-A8 の NEON と浮動小数演算最適化