D3D Shader/OpenGL」カテゴリーアーカイブ

Maya 2014 の Output Window と stderr

Maya 2014 (Windows 8 x64) で plug-in のログ出力が Output Window に
表示されなくなっていたのでしばらく悩みました。

2013 まではそのまま出ていたと思ったのですが、helloWorldCmd などの
サンプルを動かしても何も表示されないようです。
mental ray など Output Window に出力できている plug-in もあるので
API の使い方に問題があったのかもしれません。

いろいろ試したところ、stdout は出ませんが stderr なら表示できることが
わかりました。
何か使い方のルールが変わったのかもしれません。

NVIDIA Tegra4 の OpenGL ES 2.0 Extension

REGRA Tablet AT703 より、Tegra4 の GL Extension です。

Extension:
GL_OES_rgb8_rgba8
GL_OES_EGL_sync
GL_OES_surfaceless_context
GL_OES_fbo_render_mipmap
GL_NV_depth_nonliner
GL_NV_draw_path
GL_NV_draw_texture
GL_NV_texture_npot_2D_mipmap
GL_OES_EGL_image
GL_OES_EGL_image_external
GL_OES_vertex_half_float
GL_OES_mapbuffer
GL_NV_draw_buffers
GL_NV_multiview_draw_buffers
GL_EXT_color_buffer_half_float
GL_EXT_packed_float
GL_EXT_texture_rg
GL_OES_texture_half_float
GL_NV_texture_array
GL_OES_compressed_ETC1_RGB8_texture
GL_EXT_texture_compression_latc
GL_NV_texture_compression_latc
GL_EXT_texture_compression_dxt1
GL_EXT_texture_compression_s3tc
GL_NV_texture_compression_s3tc
GL_EXT_texture_filter_anisotropic
GL_NV_get_tex_image
GL_NV_read_buffer
GL_NV_shader_framebuffer_fetch
GL_NV_copy_image
GL_NV_fbo_color_attachments
GL_EXT_bgra
GL_EXT_texture_format_BGRA8888
GL_EXT_read_format_bgra
GL_EXT_unpack_subimage
GL_NV_pack_subimage
GL_NV_texture_compression_s3tc_update
GL_NV_read_depth
GL_NV_read_stencil
GL_NV_uniform_buffer_object
GL_NV_map_buffer_range
GL_EXT_robustness
GL_OES_standard_derivatives
GL_NV_EGL_stream_consumer_external
GL_EXT_separate_shader_objects
GL_NV_copy_buffer
GL_NV_3dvision_settings
GL_EXT_debug_marker
GL_EXT_debug_label
GL_KHR_debug
GL_EXT_texture_storage
GL_NV_pixel_buffer_object
GL_NV_framebuffer_blit
GL_NV_non_square_matrices
GL_NV_explicit_attrib_location
GL_OES_vertex_array_object
GL_NV_smooth_points_lines
GL_OES_texture_half_float_linear
GL_NV_texture_border_clamp
GL_OES_depth_texture
GL_OES_depth_texture_cube_map
GL_NV_shadow_samplers_cube
GL_NV_shadow_samplers_array
GL_EXT_shadow_samplers
GL_OES_depth24
GL_EXT_sRGB
GL_NV_sRGB_formats
GL_NV_generate_mipmap_sRGB
GL_EXT_occlusion_query_boolean
GL_NV_occlusion_query_samples
GL_NV_timer_query
GL_NV_framebuffer_multisamples
GL_EXT_frag_depth
GL_NV_instanced_arrays
GL_NV_draw_instanced
GL_NV_secure_context

以前の Tegra2/3 と比べて Extension の数が大幅に増えています。
Tegra3 (Nexus 7) 比で 1.7倍、初期の Tegra2 の 2倍くらいあります。

Tegra2/3 (ULP GeForce) の単なる強化版ではなく、GPU 機能そのものが
大きく変わっていることがわかります。

また NV 拡張機能の割合が非常に多くなっています。
51% も占めており、ハードウエアを使いこなすために NVIDIA がかなり力を
入れている様子が伺えます。

ただ開発サイドとしては、独自拡張よりも他社 GPU との互換性が高まった
ことの方が嬉しいというのが本音です。
例えばこれとか。

GL_OES_depth24
GL_OES_depth_texture

今まで見てきた OpenGL ES 2.0 GPU で 24bit depth が使えなかったのは
Tegra2/3 だけでした。
Tegra4 以降は広い空間のレンダリングも 24bit 前提で作ることができます。
depth_texture も同じで、ShadpwMap を使う場合 Tegra2/3 の場合だけ
別処理が必要でした。

Tegra4 はこれらの欠点を補うどころか、むしろ積極的に機能拡張が
行われているようです。

GL_EXT_shadow_samplers

OpenGL ES 3.0 では標準となる機能ですが、PowerVR SGX 5XT など一部の
GPU ではすでに使えるようになっています。
ただしフィルタリングがかかりませんでした。
未確認ですが Tegra4 はおそらく PCF に対応していると考えられます。

他にも sRGB や draw_instanced など、OpenGL ES 3.0 に対応していないものの
同等の描画が出来るだけの拡張が施されていることがわかります。

他の GPU との比較はこちら↓から。

CPU/GPU OpenGL ES Extension (Mobile GPU)

関連エントリ
Nexus 10 GPU Mali-T604
3DMark Android 版の結果から
HiSilicon K3V2 の GPU
2013/01/09:Qualcomm APQ8064 GPU Adreno 320 の速度

Nexus 10 CPU Cortex-A15 の速度

前回は浮動小数点演算のみでした。
Cortex-A15 で他のテストも走らせてみました。

CPU benchmark

前回の浮動小数点演算では Cortex-A15 が最も良い結果となりました。
単体のピーク性能は Swift/Krait と同一ですが、
64bit 2 pipe のおかげか演算効率が高くなっている印象でした。

                                  time(sec)  MB/sec  MBPS/GHz
-------------------------------------------------------------
Exynos 5D  Cortex-A15 1.7GHz  x2   1.49      72.61    42.71
A6X        Swift      1.4GHz? x2   1.75	     61.82    44.16?
APQ8064    Krait      1.5GHz  x4   2.28      47.64    31.82

single thread の core 単体の比較です。

今回のテストには NEON や浮動小数点演算は含まれていません。
この場合同一クロック時の実行性能はだいたい Swift に並ぶようです。
A6X よりも Exynos 5 Dual の方が動作クロックが高いために、
リストの中では Nexus 10 が最も良い成績となっています。

Krait は唯一の 4 core なので絶対的な速度では優っていますが
単体ではあまり伸びていません。
浮動小数点演算では成績が良かったのですが、こちらのテストでは
他の CPU に差を付けられている形となっています。

そのうち Tegra4/Exynos 5 Octa など Cortex-A15 の Quad core が出るので
システム全体のパフォーマンスとしてかなり良い成績となりそうです。
Atom では比較にならないので、Core i はともかく他の CPU と比べたくなるのも
わかる気がします。

関連エントリ
Nexus 10 CPU Cortex-A15 の浮動小数点演算速度
iPad 4/iPad mini A6X/A5 の CPU/GPU 速度
benchmark 関連

Nexus 10 CPU Cortex-A15 の浮動小数点演算速度

Nexus10 を入手したので ARMv7A の新しい CPU core 3種類が揃いました。
Apple Swift, Qualcomm Krait, ARM Cortex-A15 を比べてみます。
動作クロックが一番高いせいもありますが、
Cortex-A15 の動作は Swift よりもさらに高速でした。

                (1)     (2)     (3)     (4)     (5)     (6)     (7)
               iPad3   Nexus7  EVO 3D iPhone5  iPad4   HTL21  Nexus10
                A5X    Tegra3 MSM8660   A6      A6X   APQ8064 Exynos5D
               ARM A9  ARM A9 Scorpion Swift   Swift   Krait  ARM A15
               1.0GHz  1.2GHz  1.2GHz  1.3GHz? 1.4GHz? 1.5GHz  1.7GHz
               VFPv3   VFPv3   VFPv3   VFPv4   VFPv4   VFPv4   VFPv4
----------------------------------------------------------------------
a:m44 vmla_AQ  4.784   3.959   2.859   1.293   1.204   1.337   0.619
b:m44 vmla_BQ  2.408   2.002   1.136   1.359   1.266   0.931   0.569
c:m44 vmla_AD  4.781   3.980   3.053   1.669   1.554   1.889   0.557
d:m44 vmla_BD  2.406   2.003   1.434   1.329   1.238   1.532   0.568
A:m44 vfma_AQ  -----   -----   -----   1.632   1.519   1.882   0.746
B:m44 vfma_BQ  -----   -----   -----   1.594   1.484   0.695   0.840
e:fadds     A  4.010   3.343   3.383   3.090   2.878   2.774   2.383
f:fmuls     A  4.010   3.337   3.383   3.167   2.953   2.747   2.369
g:fmacs     A  4.012   3.337   3.379   6.180   5.757   5.574   2.956
h:vfma.f32  A  -----   -----   -----   6.180   5.756   2.747   2.957
i:vadd.f32 DA  4.111   3.426   3.377   3.091   2.877   2.762   1.183
j:vmul.f32 DA  4.110   3.421   3.383   3.168   2.950   2.746   1.478
k:vmla.f32 DA  4.512   3.792   3.380   3.166   2.951   5.604   1.480
l:vadd.f32 QA  8.023   6.688   3.377   3.090   2.878   2.801   2.365
m:vmul.f32 QA  8.022   6.681   3.384   3.166   2.952   2.761   2.364
n:vmla.f32 QA  8.025   6.681   3.380   3.167   2.950   5.606   2.367
o:vfma.f32 DA  -----   -----   -----   3.167   2.494   2.833   1.479
p:fadds     B  4.014   3.347   5.917   6.181   5.756   3.467   2.956
q:fmuls     B  5.013   4.195   5.917   6.180   5.756   3.556   3.558
r:fmacs     B  8.023   6.688   8.451  12.361  11.514   6.298   5.912
s:vfma.f32  B  -----   -----   -----  12.363  11.513   3.430   5.910
t:vadd.f32 DB  4.113   3.421   5.916   3.090   2.881   3.529   2.958
u:vmul.f32 DB  4.118   3.422   5.073   3.169   2.949   3.447   2.364
v:vmla.f32 DB  9.027   7.561   8.451   6.180   5.755   6.293   4.728
w:vadd.f32 QB  8.021   6.705   5.916   3.090   2.879   3.457   2.961
x:vmul.f32 QB  8.029   6.683   5.074   3.167   2.950   3.428   2.363
y:vmla.f32 QB  9.026   7.532   8.457   6.179   5.759   6.372   4.729
z:vfma.f32 DB  -----   -----   -----   6.181   5.755   3.437   4.730
----------------------------------------------------------------------
↑数値は実行時間(秒) 数値が小さい方が速い

(1)=Apple iPad 3          A5X      Cortex-A9  x2 1.0GHz  VFPv3 i6.1
(2)=ASUS Nexus 7          Tegra 3  Cortex-A9  x4 1.2GHz  VFPv3 A4.2
(3)=HTC EVO 3D ISW12HT    MSM8660  Scorpion   x2 1.2GHz  VFPv3 A4.0
(4)=Apple iPhone 5        A6       Swift      x2 1.3GHz? VFPv4 i6.1
(5)=Apple iPad 4          A6X      Swift      x2 1.4GHz? VFPv4 i6.1
(6)=HTC J butterfly HTL21 APQ8064  Krait      x4 1.5GHz  VFPv4 A4.1
(7)=Samsung Nexus 10      Exynos5D Cortex-A15 x2 1.7GHz  VFPv4 A4.2

テスト項目の詳細は下記参照 (a:~z:)

Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力

iPad4/EVO 3D/Butterfly は計測しなおしたため以前よりも数値が上がっています。

a:~d: を見ると 1.7GHz の Cortex-A15 は Swift の倍近い数値となっています。
命令単体でも効率が上がっており、Krait と比べても 64bit D (float2) 命令は
クロック差以上の速度となっています。

64bit D (float2) と 128bit Q (float4) に差があることから、おそらく
Cortex-A15 は 64bit 単位の ALU が 2 pipe 存在しているのではないでしょうか。
128bti Q (float4) 時の速度は Swift/Krait と大きな違いがないので
演算能力のピークレートは自体は Swift/Krait と同一でしょう。
D, Q の差がない Scorpion/Swift/Krait は 128bit 単位だと考えられます。

(1)~(3) Cortex-A9/Scorpion の a:~d: では AQ/AD と BQ/BD の結果に
大きな違いが生じています。
これが CPU 世代間の違いとなっており、(4)~(7) の Swift/Krait/Cortex-A15
では命令順に依存せずに一定の効率で実行できている事がわかります。

以前も書いたとおり Swift はスカラーの積和命令だけ遅くなっています。
NEON のベクターでは積和でも特に速度が落ちていないため、
何らかの構造的な理由によるものと思われます。

同じように Krait にも苦手なパターンがあります。
ARM では VFPv4 以降 FMA (Fused Multiply add) 命令が追加されています。
Krait は vfma (FMA) よりも従来の vmla 命令が倍近く遅くなっています。
中間丸め込みを行うために vmul + vadd に展開されている可能性があります。

●Krait 最適化

a:~d: の演算は vmla を使っていますが、この命令は Krait では低速となっています。
vfma に置き換えることで高速化できる可能性があるので試してみました。

// A: mat44 neon_AQ の vfma 化

   vmul.f32  q8, q0, d8[0]
   vlma.f32  q8, q1, d8[1]
   vlma.f32  q8, q2, d9[0]
   vlma.f32  q8, q3, d9[1]
    :
↓
   vmul.f32  q8, q0, d8[0]
   vdup.f32  q9,  d8[1]
   vfma.f32  q8, q1, q9
   vdup.f32  q10, d9[0]
   vfma.f32  q8, q2, q10
   vdup.f32  q11, d9[1]
   vfma.f32  q8, q3, q11
    :
// B: mat44 neon_AQ の vfma 化

   vmul.f32  q8,  q0, d8[0]
   vmul.f32  q9,  q0, d10[0]
   vmul.f32  q10, q0, d12[0]
   vmul.f32  q11, q0, d14[0]
   vmla.f32  q8,  q1, d8[1]
   vmla.f32  q9,  q1, d10[1]
   vmla.f32  q10, q1, d12[1]
   vmla.f32  q11, q1, d14[1]
    :
↓
   vmul.f32  q8,  q0, d8[0]
   vmul.f32  q9,  q0, d10[0]
   vmul.f32  q10, q0, d12[0]
   vmul.f32  q11, q0, d14[0]
   vdup.32   q12, d8[1]
   vdup.32   q13, d10[1]
   vdup.32   q14, d12[1]
   vdup.32   q15, d14[1]
   vfma.f32  q8,  q1, q12
   vfma.f32  q9,  q1, q13
   vfma.f32  q10, q1, q14
   vfma.f32  q11, q1, q15
    :

vfma は vmla と違い vector * scalar ができないので、
単純に置換するだけでは動きません。
SSE と同じようにデータのコピーが必要となるので vdup を挿入しています。

               ARM A9  ARM A9 Scorpion Swift   Swift   Krait  ARM A15
----------------------------------------------------------------------
a:m44 vmla_AQ  4.784   3.959   2.859   1.293   1.204   1.337   0.619
b:m44 vmla_BQ  2.408   2.002   1.136   1.359   1.266   0.931   0.569
    ↓
A:m44 vfma_AQ  -----   -----   -----   1.632   1.519   1.882   0.746
B:m44 vfma_BQ  -----   -----   -----   1.594   1.484   0.695   0.840

A: はかなり遅いですが、B: は効果がありました。
このケースでは Krait が Cortex-A15 を超えています。

予想通り Swift , Cortex-A15 にとっては逆効果で、vdup が増えた分だけ遅くなりました。

なお vmla と vfma は丸め込みのタイミングが異なるので厳密には結果は一致しません。
vfma の方が誤差が少ないのですが、Cのコードで普通に書くと fmacs になるので
検証コードで見事に assert に引っかかりました。

関連エントリ
2013/01/09:Qualcomm APQ8064 GPU Adreno 320 の速度
2012/12/23:Qualcomm APQ8064 Krait/A6 swift の浮動小数点演算能力

Nexus 10 GPU Mali-T604

Nexus 10 のデータを追加しました。
Nexus 10 の Exynos 5 Dual は Krait + Adreno 320 の APQ8064 と同じように、
CPU (Cortex-A15)、GPU (ARM Mali-T604) ともに新しい世代の core が用いられています。

Mobile GPU の OpenGL ES Extension

下記 GPU 機能の比較表も更新しました。

Mobile GPU の機能比較表

Mali-T604 は OpenGL ES 3.0 世代の GPU ですが、今のところ使えるのは
Adreno 320 同様 OpenGL ES 2.0 API の範囲に限られます。

Adreno の場合 OpenGL ES 2.0 API でも ETC2/EAC Texture など、
部分的に OpenGL ES 3.0 の機能が取り込まれていました。
Mali-T604 では特に OpenGL ES 3.0 を先取りしているような部分はないようです。

新しい core なので動作速度も十分高速でシェーダーパフォーマンスも良好です。
前世代の Mali-400MP では TBR ながら discrete 構成で頂点性能に難がありました。
Mali-T604 は Unified Shader となったため総合的に性能が上がっています。
構造の違いは機能面からもわかります。

例えば Shader Constant (Uniform) 数、Vertex Texture mapping 、
Pixel Format/Vertex Format、Shader の演算精度など、
さまざまな面で Vertex と Pixel (Fragment) の機能差が無くなっています。

Uniform数      Vertex Fragment
----------------------------------------
Tegra2/3        256    1024     discrete
Mali-400MP      128    1024     discrete
Mali-T604       256     256     unified
Adreno          251     221     unified
PowerVR SGX 5   128      64     unified

Tegra2/3, Mali-400MP の Fragment Shader は Uniform 数に 1024 と極端に
大きな値を返しています。
おそらく古い GeForce と同じように、Pixel (Fragmen) の場合だけ
Shader Program のバイナリを直接書き換える仕組みで、
事実上制限が無いのだと思われます。

T604 は Vertex / Fragment との差がなく他の GPU に近い数値になりました。

これまで Unified Shader の GPU は大きく分けて、highp 固定精度と
highp/mediump/lowp 可変精度の 2種類ありました。

Unified Shader GPU     Precision
---------------------------------------------------------
Adreno 200/300         highp のみ          (highp 固定)
Vivante GC             highp のみ          (highp 固定)
PowerVR SGX 5          highp/mediump/lowp  (3種類の可変)
Mali-T604              highp/mediump       (lowp 無し)

Mali-T604 は PowerVR のように precision 宣言が有効ですが、
highp と mediump の 2種類しかありません。
mediump 固定で lowp が無かった Mali-400MP に似ています。

highp に対応しているにも関わらず GL_OES_fragment_precision_high が
無いので、Mali-400MP と同じように Fragment Shader (PixelShader) では
mediump を使って欲しいのかもしれません。

ただし下記の記事にも書いたように glGetShaderPrecisionFormat() の返す値は
実際の動作と異なっている場合があります。まだ実測していません。

OpenGL ES 2.0 GLSL precision 宣言と GPU 毎の演算精度を調べる
Mobile GPU の比較 Precision

●全然関係ないシェーダーのはまり

GPU 機能とは関係なく、Nexus 10 の解像度の高さに自分のシェーダーが対応できて
いませんでした。
もともと浮動小数点の演算を利用して複数のデータを圧縮して格納していたのですが、
2560×1600 のスクリーン座標がオーバーフローしていることが原因でした。
やはり演算精度は実機できちんと測定しておいた方がよさそうです。

関連エントリ
Qualcomm APQ8064 GPU Adreno 320 の速度
OpenGL ES 2.0 GLSL precision 宣言と GPU 毎の演算精度を調べる
GPU 速度に関連するエントリ