Qualcomm APQ8064 GPU Adreno 320 の速度

今までテストに使用してきたプログラムが安定して動作しないため
Adreno 320 では速度の計測ができていませんでした。
LG Optimus G LGL21 を借りることができたのでもう一度テストしてみました。

Mobile GPU ベンチ OpenGL ES 2.0
CPU benchmark
OpenGL ES Extension (Mobile GPU)

GPU bench の (1) 以外は 60fps に達するため数値が出ていません。
GPU 性能が上がったため、もはやこのテストは計測に向いていないことになります。

また Adreno 320 は OpenGL ES 3.0 世代の GPU ですが、
現在の OS から使う限り API は OpenGL ES 2.0 になります。
GPU 性能をまだ引き出せていない可能性があります。

テストプログラムのエラーの原因は特定のケースでシェーダーのコンパイルが
エラーになるもので、回避方法はわかったもののまだ詳しい条件が
特定できていません。

VFP test では HTC J HTL21 よりも良い結果が出ています。

                 (1)     (2)     (3)      (4)    (5)     (6)
                 iPad3  Touch5   EVO 3D  iPad4 Butterfly OptimusG
                 A5X     A5      8660     A6X    8064    8064
                 C-A9    C-A9   Scorpion Swift   Krait   Krait
----------------------------------------------------------------
a:mat44 neon_AQ  4.784   5.979   2.879   1.204   1.919   1.354
b:mat44 neon_BQ  2.408   3.008   1.146   1.266   1.273   0.930
c:mat44 neon_AD  4.781   5.974   3.079   1.554   2.453   1.862
d:mat44 neon_BD  2.406   3.007   1.440   1.344   2.041   1.521
e:fadds      A   4.010   5.013   3.460   2.882   3.791   2.831
f:fmuls      A   4.010   5.012   4.361   2.953   3.671   2.793
g:fmacs      A   4.012   5.011   4.034   5.763   7.334   5.599
h:vfma.f32   A   -----   -----   -----   5.765   3.725   2.743
i:vadd.f32 D A   4.111   5.136   3.493   2.877   3.706   2.724
j:vmul.f32 D A   4.110   5.136   3.502   2.950   3.667   2.767
k:vmla.f32 D A   4.512   5.650   3.638   2.951   7.557   5.462
l:vadd.f32 Q A   8.023  10.036   3.408   2.878   3.677   2.717
m:vmul.f32 Q A   8.022  10.028   3.427   2.952   3.647   2.741
n:vmla.f32 Q A   8.025  10.028   3.400   2.955   7.362   5.446
o:vfma.f32 D A   -----   -----   -----   2.494   3.676   2.709
p:fadds      B   4.014   5.013   5.972   5.757   4.664   3.388
q:fmuls      B   5.013   6.265   5.960   5.760   4.583   3.384
r:fmacs      B   8.023  10.024   8.573  11.521   8.266   6.246
s:vfma.f32   B   -----   -----   -----  11.519   4.611   3.622
t:vadd.f32 D B   4.113   5.137   5.945   2.881   4.746   3.406
u:vmul.f32 D B   4.118   5.145   5.098   2.951   4.680   3.454
v:vmla.f32 D B   9.027  11.278   8.498   5.757   8.361   6.140
w:vadd.f32 Q B   8.021  10.023   5.950   2.879   4.702   3.481
x:vmul.f32 Q B   8.029  10.023   5.095   2.951   4.595   3.412
y:vmla.f32 Q B   9.026  11.277   8.497   5.762   8.464   6.249
z:vfma.f32 D B   -----   -----   -----   5.759   4.660   3.413
---------------------------------------------------------------
↑数値は実行時間(秒) 数値が小さい方が速い

(1)=Apple iPad 3           A5X      ARM Cortex-A9 x2  1.0GHz
(2)=Apple iPod touch 5     A5       ARM Cortex-A9 x2  0.8GHz
(3)=HTC EVO 3D ISW12HT     MSM8660  Scorpion      x2  1.2GHz
(4)=Apple iPad 4           A6X      A6 (swift)    x2    ?GHz
(5)=HTC J butterfly HTL21  APQ8064  Krait         x4  1.5GHz
(6)=LG Optimus G LGL21     APQ8064  Krait         x4  1.5GHz

Krait の FP 性能は Swift に並ぶ新 core であることがよくわかります。

前回のテスト時はクロックが上限まで上がっていなかった可能性があります。
HTC J butterfly が修理から戻ってきたらもう一度計測してみたいと思っています。

関連エントリ
Adreno 320 Snapdragon S4 Pro APQ8064

Qualcomm APQ8064 GPU Adreno 320 の速度」への24件のフィードバック

  1. chototsu

    お久しぶりです。
    Adreno320はかなり速いようですね。
    しかしこちらはトラブルで苦しんでます。
    症状は、トゥーンシェードの輪郭線を書くとテクスチャが黒くなってしまうというものです。
    テクスチャを使っていない部分は正しく表示できています。
    また輪郭も問題無く書けています。
    しかしテクスチャだけが黒くなるのです。
    同じ画面の、輪郭を書いていない部分のテクスチャは正しく表示されます。また、輪郭を書くのをやめると全部正しく表示されます。
    輪郭は、同じvboを法線方向に引き延ばして書いています。
    もしかするとvboを使い回すと干渉するのかもしれません。
    しかし、輪郭は後から書いているのに、先に書いている部分がおかしくなるのは実に不可思議です。
    内部の並列化でおかしくなっているのでしょうか。

  2. oga 投稿作成者

    chototsu さんお久しぶりです。
    興味あるので、もし良ければこちらでも試してみたいと思います。
    プログラムをいただくことは可能でしょうか。
    修理に出していた HTL21 (APQ8064 Adreno 320) が復活しました。

  3. chototsu

    テストプログラムのapkをメールフォームからお送りしました。
    ソースはまだなのですが、今度最小限に削った物を作ってお送りします。

  4. oga 投稿作成者

    わざわざありがとうございます。
    赤い輪郭だけ表示されていて、中が黒い状態なのを確認しました。
    一番上のモデル以外はきちんと表示されているようです。
    モーション無しで 50~60fps くらい。

  5. chototsu

    メニュー、設定、輪郭線の太さをedge offにすると、表示されるはずです。輪郭線を書くとご覧のような状態になります。
    現在市場にあるほとんどのGPUで動いているためレンダラのバグでは無いと思うのですが・・・。

  6. oga 投稿作成者

    まだlibを展開できておらずシェーダーとか描画周りを
    見ていないのですが、AVD でも同じ症状が出ました。
    GPU だけが原因とは言い切れないようです。

    AVD : API Level 16 (ARM armeabi-v7a) "GPU emulation" Yes
    HOST-GPU: Intel HD4000

  7. chototsu

    テスト有り難うございます。
    エミュレータでも再現しましたか。
    エミュレータがOpenGL ES2.0に対応した直後に試したときはエミュレータでも動作したのを確認したのですが・・・。
    ホストOSのGPUの違いでしょうか。
    こちらはMacOSXでGPUはRadeon HD 6750Mです。
    もう一度最新バージョンで確認してみます。

  8. chototsu

    うーん、こちらの環境ではエミュレータでも動いていますね・・・。
    ということは、Snapdragon S4 ProとIntel HD4000で駄目ということでしょうか。

  9. oga 投稿作成者

    rendering も java で行われているようですね。
    render state とかシェーダーとか影響を与えている命令を
    絞り込めればと思ったのですが、すぐには無理そうです。
    とりあえず手持ちの環境でいろいろ試してみます。

  10. chototsu

    物理エンジン以外は全部Javaです。
    ですので、Windowsなどでも動きます。
    レンダラのコードはOGLESShaderRenderer.javaにあります。
    とりあえず再現出来る環境が無いとどうしようも無さそうなので購入を検討していますがまだまだ高いですね。
    NEXUS4が日本で売られれば良いのですが。

  11. chototsu

    御陰さまで解決しました。
    まさかテクスチャユニットがシェーダに関連づけられているとは思いませんでした。
    確かにその方がアーキテクチャとしては自然です。
    nvidiaも私が持っているTegra2,3やGeForce 9600GTなどではグローバルな状態として扱われていますが、最新の物ではそうなっているのですね。
    勉強になりました。

  12. chototsu

    お久しぶりです。
    またAdreno320でトラブってます。
    今回のトラブルはFrameBufferのdepth bufferがおかしいというものです。
    今うちでAndroidを利用したOculus Riftのようなデバイスを作っているのですが、
    http://www.nicovideo.jp/watch/sm21353318
    このシェーダがAdreno320だけで動きません。
    具体的にはこのようなノイズが乗ってしまいます。
    https://plus.google.com/105454326907346241584/posts/2nzfUHzNGF5
    ノイズが乗るのは右目だけで左目用の部分は乗りません。
    やっている事は、FrameBufferに一旦普通に描画し、それをテクスチャとして読み込んでレンズの歪みの変形を行っています。
    なぜdepth bufferがおかしいと思うかといいますと、depth testをoffにすると描画されるからです。color bufferは問題無いようです。
    ノイズですが、どうもOpenGLのcontextの外の画像を拾っているようです。理由は、notificationなどが出るとそれと思しきパターンがノイズに現れるからです。
    depth bufferにはGL_DEPTH_COMPONENT16でrenderbufferを割り当てています。
    (割り当てを外すとさらに描画が滅茶苦茶になりますので、間違い無く割り当てられていると思います)
    何かヒントを頂けないでしょうか。

  13. oga 投稿作成者

    ステレオ(立体視)レンダリングでしょうか。
    このケースではレンダリングの順番が問題になるかもしれません。
    具体的にどのような順番でレンダリングしていますか?

    ・左右別のバッファを確保して、交互にレンダリング
    ・1つのバッファに右レンダリング、次に左レンダリング、など

    以前の depth 値を再利用とかしてないでしょうか。
    例えば

    1. RenderTarget A に rendering
    2. RenderTarget B に rendering
    3. RenderTarget A の画像の上に上書きする

    など。
    TBL な GPU では以前のバッファ内容を保ったまま RenderTarget を頻繁に
    切り替えると負荷が上がるので、その辺りで問題が生じるかもしれません。

    また最近の GPU は、正しく clear 命令を発行しないとバッファがクリア
    されない可能性があります。

    試してませんが Adreno 320 では IMR に切り替えられるので、
    結果が変わる可能性があります。こちらでも調べてみます。

    あと 24bit depth でも同じ結果でしょうか。

  14. chototsu

    アドバイス有り難うございます。
    FrameBufferは左右別々に用意しています。
    描画はこんな順序です。
    1.左右のFrameBufferを個別に作成する。
    2.左目用のFrameBufferにsceneを描画。
    3.右目用のFrameBufferにsceneを描画。
    4.左目用のFrameBufferをテクスチャとして取り出し、レンズの歪み変換をかけ画面に描画。
    5.右目用のFrameBufferをテクスチャとして取り出し、レンズの歪み変換をかけ画面に描画。

    レンズの歪みの変換はフラグメントシェーダで行っています。
    FrameBufferは別個に用意していますからdepth値の再利用は行っていません。
    glClearにGL_DEPTH_BUFFER_BITを立てて何度もクリアしていますが、color bufferのみクリアされ、depth bufferはノイズが乗ったままです。

    FrameBufferの切り替えは正しく出来ているはずです。ノイズが乗るものの描画自体は間違っていません。
    glGetErrorもチェックしていますがエラーは全くありません。

    左目用の画面は正しく描画されますので、送っているコマンド自体は間違ってないと思うのですが・・・。

    アプリはこちらで公開しています。
    https://play.google.com/store/apps/details?id=info.projectkyoto.mms.tinyvr
    cube map onにして背景を描画するとノイズの乗り方が分かりやすいです。

    24bit depthは後で試してみます。
    IMRの切り替えはどうすればいいのでしょうか?

  15. oga 投稿作成者

    FrameBuffer に attach した depth buffer も左右別でしょうか。

    FrameBuffer に問題は出ていないでしょうか。
    glCheckFramebufferStatus( GL_FRAMEBUFFER ) で確認できます。

    左右逆順でレンダリングした場合はどうでしょう。

    最後の合成時 (4.,5.) も depth buffer は有効でしょうか。

    IMR への切り替えは下記の命令で行うようです。
    実際に試したわけではないのでとりあえず引用だけ。

    glHint( GL_BINNING_CONTROL_HINT_QCOM, GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM );

    GL_BINNING_CONTROL_HINT_QCOM 等のシンボルは NDK ヘッダにはないですが、
    khronos の最新の gl2ext.h や下記に記載されてます。
    http://www.khronos.org/registry/gles/extensions/QCOM/QCOM_binning_control.txt

  16. chototsu

    アドバイス有り難うございます。
    24bit depthを試しました。
    ノイズがさらに悪化しました。
    > glCheckFramebufferStatus( GL_FRAMEBUFFER ) で確認できます。
    FrameBufferを切り替える時に毎回行っています。
    結果はすべてGL_FRAMEBUFFER_COMPLETEです。

    > 左右逆順でレンダリングした場合はどうでしょう。
    現象も逆になりました。左側にノイズが乗り、右側は正常でした。
    ちなみに先にレンダリングした方は正常、後にレンダリングした方にノイズが乗ります。

    > 最後の合成時 (4.,5.) も depth buffer は有効でしょうか。
    有効になっていました。試しに無効にしましたが結果は同じでした。
    ノイズが乗るのは2と3の段階です。理由は、ノイズにも4,5の歪みのフィルターがかかっている事、2,3で画面をべた塗りするとノイズも消える事です。

    IMRへの切り替えはこれから試します。

  17. chototsu

    IMRへの切り替えを行ってみました。
    Javaで以下を実行しました。
    GLES20.glHint(0x8FB0, 0x8FB3);
    結果は変わりませんでした。

  18. oga 投稿作成者

    FrameBuffer に attach した depth buffer は左右別に確保したものでしょうか。
    FrameBuffer と depth の解像度(サイズ)はいくつでしょう。

    当たり前と思われるかもしれませんが、やはり 1つ1つ設定を
    確認していくしか無いと思います。
    例えば最初の描画終了時に DepthMask を FALSE にしたまま
    2回目の Clear が呼ばれて depth buffer がクリアされてないとか。

    Framebuffer/Renderbuffer (256×256 RGBA8888, depth16) を 2つ
    作ってTexture に 3D レンダリングしてみましたが Adreno320
    でも動いているようです。
    (HTL21 Android 4.1.1 GLES 2.0)

    IMR 切り替えはうまく行かないようですね。
    余裕ができたら IMR/TBR の切り替えあたりは試したいと思ってます。

  19. chototsu

    動きました。
    まさにおっしゃるとおり、glDepthMaskが原因でした。
    glClearの前にglDepthMaskを毎回呼ぶようにすると動きました。
    大変助かりました。有り難うございます。
    ただ腑に落ちないのは、前のバージョンでもPowerVR 540やTegra3では問題無く動いている事です。
    もしglDepthMask(false)のままglClearを呼べば同じ問題が生じるはずなのですが・・・。
    また、クリア出来ていないだけなら前の残像が残るだけで、砂嵐のようなちらつきは発生しないはずです。

    前回のトラブルの原因になった、テクスチャユニットがシェーダに関連づけられているのと同じような仕様変更があったのでしょうか。

    書き忘れましたがテスト機は
    HTC J BUTTERFLY HTL 21(K)
    です。

  20. oga 投稿作成者

    動いてよかったです。
    いろいろと面白そうなアプリを作ってらっしゃるようですね。

    未定義バッファの読み取りは動作が不定なので、
    GPU やドライバによってはそのまま動作してしまうことが
    あったのではないかと思います。

    特に Framebuffer のクリアは GPU にとって違いが生じる部分で、
    内部構造がそれぞれ異なっています。
    depth ではフラグを立てるだけで値を書き込まないものも多いです。

    今回の症状も HW 構造を考えるといろいろわかります。
    タイル構造を視認できたので貴重な経験だったと思います。

    OpenGL に関しては私自身あまりよく理解していない部分があります。
    今更なのですが VAO の挙動を D3D と同じものだと
    勘違いしていました。
    仕様変更ではなく、私の理解が足りなかっただけだと思ってます。

    シェーダーとオブジェクトのバインド周りも、
    きちんと仕様を理解するために
    ちょうどこれから解析してみようと考えていました。

  21. chototsu

    有り難うございます。
    元々Oculus Rift用に作り始めたのですがOcurus Riftが入手出来なかったためAndroidに移植しました。
    シェーダーが相当重いので無理かと思ったのですがやってみるとそこそこ動いたので驚いています。最近のスマホは凄いですね。
    尚、ハードとソフトはオープンソースで公開の予定です。

    ところでまた質問で恐縮なのですが、うちのゲームエンジンを使って別の方が独自にOculus Rift用のシェーダを書かれました。
    https://www.youtube.com/watch?v=dHz8uaDSd7I

    その方からソースを頂いたのですが、うちのMacBook Proでは、Radeon HD 6750Mでは動きませんでした。Intel HD Graphics3000に切り替えると動きます。
    原因を探ると以下の行が駄目でした。
    float dy = cos(m_Dist*pos.x*m_Fov.x/180.0*PI+m_XShift/180.0*PI)*pos.y;

    これをこう書き換えるとRadeonでも動きました。
    float dy = cos((m_Dist*pos.x*m_Fov.x+m_XShift)/180.0*PI)*pos.y;

    Radeon以外では上の式で問題無く動いています。
    Radeonですと結果がNaNか何かになってしまうらしく、真っ黒になってしまいます。
    無駄な演算があるのでオプティマイズがバグるのでしょうか。

  22. oga 投稿作成者

    MacBook ということは OpenGL 3.2 でしょうか。
    GeForce では動作するのでしょうか。

    入力値に何らかの不正な値が含まれている可能性はないでしょうか。
    Intel HD3000 と違い RADEON HD6000 は OpenCL に対応しており、
    IEEE754 に対してより厳密な実装となっている可能性があります。
    以前の GPU はそこまで求められておらず、
    描画が継続されているだけかもしれません。

    また下の式よりも上の式の方が無駄とは認識しないので、
    両者の違いは書いた通りの演算順番だと思います。

    もちろんドライバを頻繁に更新していない場合は
    シェーダーコンパイラのバグの可能性もあるかと思います。

    やはり GLSL は GPU 毎にコンパイラも違うので、
    D3D よりも考えられる問題範囲が広いのが難点だと思います。

  23. chototsu

    ご回答有り難うございます。
    他のGPUでは問題無く、私が知る限りトラブルがあったのはMacのRadeon HD 6750Mだけです。
    m_と付く変数はJavaから渡しているuniformで、固定値です。Javaから渡していますのでそんな変な数値が入るとは考え難いのですが・・・。
    それにしてもこのレベルでトラブルが発生してしまうと、GLSLのデバッグは本当に大変ですね。

コメントは停止中です。