Important: アプリケーションのパフォーマンスをチューニングする場合、最初の手順は通常、ア プリケーションのボトルネックとなっている段階とその理由を特定することです。
3. OpenGL ESのコンテキストをフラッシュして、この間に描画した内容が表示されないようにしま す。
OpenGL ESの状態に注意を払う
iOSにおけるOpenGL ESアプリケーションのパフォーマンスは、OS Xやその他のデスクトップオペレー
ティングシステムにおけるOpenGLのパフォーマンスとは異なります。iOSベースのデバイスは強力な 計算デバイスですが、デスクトップコンピュータやラップトップコンピュータが持つメモリやCPUパ ワーは持ち合わせていません。組み込みのGPUは典型的なデスクトップやラップトップのGPUとは異 なるアルゴリズムを使用しており、メモリと電力の使用を抑えるように最適化されています。グラ フィックスデータのレンダリングが非効率的であると、フレームレートが低下したり、iOSベースの デバイスのバッテリー持続時間が著しく減少したりする可能性があります。後の章では、アプリケーションのパフォーマンスを向上させる数多くのテクニックを取り上げていま す。この章では全体的な戦略について説明します。特に注記しない限り、この章に挙げる事項はどの 版のOpenGL ESにも適用できます。
XcodeやInstrumentsで、アプリケーションをデバッグ、プロ ファイリングする
アプリケーションは、さまざまなデバイス上で、さまざまなシナリオに基づいてパフォーマンスをテ ストするまでは最適化しないでください。XcodeやInstrumentsには、性能を見極め、問題点を修正す るためのツールが付属しています。
●
Xcodeのデバッグゲージで性能を概観できます。Xcode上でアプリケーションを実行すれば、この
ゲージは常に表示されるので、開発の過程で性能に変化が生じればすぐに気がつくでしょう。
●
Instrumentsに付属する、OpenGL ES AnalysisおよびOpenGL ES Driverというツールで、実行時の性
能をさらに詳しく調べることができます。アプリケーションがリソースをどのように使っている か、OpenGL ESのベストプラクティスに適合しているか、といった詳しい情報が得られます。ま た、グラフィックスパイプラインの一部を選択的に無効にすることにより、顕著なボトルネック になっている箇所を判断できます。詳細については、『Instruments User Guide』を参照してくだ さい。●
Xcodeに付属する、OpenGL ES Frame DebuggerおよびPerformance Analyzerというツールで、性能
やレンダリングに関する問題の箇所を特定し、対処できます。あるフレームのレンダリングおよ び表示に使われたOpenGL ESのコマンドをすべて取り込み、OpenGL ESの状態、バインドされたリ ソース、出力フレームバッファに対して、各コマンドがどのような効果を及ぼしているか確認し ます。また、シェーダのソースコードを表示、編集し、変更を施したとき出力画像にどんな変化OpenGL ES アプリケーションのチューニング
が現れるか調べることも可能です。OpenGL ES 3.0対応のデバイスであれば、Frame Debugger上 で、レンダリング時間の多くを占めている描画関数やシェーダ命令も分かります。ツールについ て詳しくは、“Xcodeに付属するOpenGL ES用ツールの概要” (126 ページ)を参照してください。
XcodeやInstrumentsでOpenGL ESのエラーを監視する
APIの使い方が誤っていると、OpenGL ESがエラーになります(基盤となるハードウェアが実行できな
い演算を要求するなど)。コンテンツが正しくレンダリングされた場合でも、これらのエラーはパ フォーマンス上の問題を示すことがあります。OpenGL ESのエラーをチェックする従来の方法はglGetError
関数を呼び出すことですが、この関数を繰り返し呼び出すと、パフォーマンスが大幅に低下する可能性があります。代わりに上記のツールで、次のように調べてください。
●
Instrumentsでアプリケーションをプロファイルすると、ツール「OpenGL ES Analyzer」の詳細ペイ
ンが表示され、記録中にレポートされたOpenGL ESのエラーが表示されます。
●
Xコードでアプリケーションをデバッグしているときに、フレームを取り込み、そのフレームの
生成に使用された描画コマンドのほか、それらのコマンドの実行中に発生したエラーを確認する ことができます。
OpenGL ESエラーの発生時にプログラムの実行を停止するようにXcodeを設定することもできます。
(「OpenGL ESのエラーブレークポイントの追加」を参照。)
XcodeやInstrumentsで、アプリケーションをデバッグ、プロファイリングする
情報提供のデバッグおよびプロファイル用に、 OpenGL ES のコードに注釈 を付ける
OpenGL ESコマンドを論理的なグループにまとめ、OpenGL ESオブジェクトに意味のあるラベルを追加
することによって、より効率的にデバッグとプロファイルを行うことができます。これらのグループ とラベルは、XcodeのOpenGL ES Frame Debugger(図 7-1を参照)と、InstrumentsのOpenGL ES Analyzer に表示されます。グループとラベルを追加するには、EXT_debug_markerおよびEXT_debug_label拡 張機能を使用します。図 7-1 デバッグマーカグループの追加前と追加後のXcode Frame Debugger
1つの意味のある演算を表す一連の描画コマンド(たとえば、ゲームのキャラクタの描画など)があ
るときは、マーカを使用してデバッグ用にそれらをグループ化することができます。リスト 7-1に、これらの関数を使用して、テクスチャ、プログラム、頂点配列をグループ化し、シーンの1つの要素 に対する呼び出しを描画するコード例を示します。まず
glPushGroupMarkerEXT
関数で意味のある名 前を与えた後、OpenGL ESのコマンド群を実行します。最後にglPopGroupMarkerEXT
関数で、一連の コマンドが終了したことを示します。XcodeやInstrumentsで、アプリケーションをデバッグ、プロファイリングする
リスト 7-1 デバッグマーカを使って描画コマンドに注釈をつけるコード例
glPushGroupMarkerEXT(0, "Draw Spaceship");
glBindTexture(GL_TEXTURE_2D, _spaceshipTexture);
glUseProgram(_diffuseShading);
glBindVertexArrayOES(_spaceshipMesh);
glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT, 0);
glPopGroupMarkerEXT();
複数の入れ子になったマーカを使用して、複雑なシーンに意味のあるグループの階層を作成すること ができます。
GLKView
クラスを使用してOpenGL ESコンテンツを描画すると、すべてのコマンドが描 画メソッドに含まれる「Rendering」グループが自動的に作成されます。作成するすべてのマーカが このグループ内で入れ子になります。ラベルを使用して、テクスチャ、シェーダプログラム、頂点配列オブジェクトなどのOpenGL ESオブ ジェクトに意味のある名前を付けることができます。
glLabelObjectEXT
関数でオブジェクトに名前 を与え、デバッグやプロファイルの際に表示されるようにします。リスト 7-2に、この関数で頂点配 列オブジェクトにラベル付けをするコード例を示します。GLKTextureLoader
クラスを使用してテク スチャデータを読み込むと、それらのファイル名で作成されたOpenGL ESテクスチャオブジェクトに 自動的にラベルが付けられます。リスト 7-2 デバッグラベルを利用してOpenGL ESオブジェクトに注釈をつけるコード例
glGenVertexArraysOES(1, &_spaceshipMesh);
glBindVertexArrayOES(_spaceshipMesh);
glLabelObjectEXT(GL_VERTEX_ARRAY_OBJECT_EXT, _spaceshipMesh, 0, "Spaceship");
パフォーマンスのための一般的な推奨事項
常識に従って、パフォーマンスチューニングの作業を進めます。たとえば、アプリケーションがフ レームごとに数十個程度の三角形を描く場合、頂点データの送信方法を変更するとパフォーマンスが 向上する可能性が低くなります。作業のパフォーマンスを最も向上させる最適化を探します。
シーンのデータが変更された場合のみシーンを再描画する
アプリケーションは、シーン内に何らかの変更があるまで新しいフレームのレンダリングを待機する 必要があります。
Core Animation
はユーザに表示された最後の画像をキャッシュし、新しいフレーム が表示されるまでその画像を表示し続けます。パフォーマンスのための一般的な推奨事項
データが変化した場合でも、必ずしもハードウェアがコマンドを処理するのと同じ速度でフレームを レンダリングする必要はありません。一般に、高速でもフレームレートが変動する場合と比べると、
より低速で固定のフレームレートのほうがユーザには滑らかに見えます。ほとんどのアニメーション では30フレーム/秒の固定フレームレートで十分であり、電力消費の削減に役立ちます。
使用しないOpenGL ES機能を無効にする
最高の処理性能が得られるのは、アプリケーションが何も計算せずに済む場合です。たとえば、事前 に計算を行って、結果をモデルのデータに格納できる場合は、アプリケーション実行時にその計算の 実行を回避することができます。
OpenGL ES 2.0以降向けにアプリケーションを記述する場合は、アプリケーションがシーンのレンダリ
ングに必要とする各タスクを実行するための、多数のスイッチと条件が設定された単一のシェーダを 作成しないでください。代わりに、各シェーダが的を絞った特定のタスクを実行する、複数のシェー ダプログラムをコンパイルします。アプリケーションでOpenGL ES 1.1を使用する場合は、シーンのレンダリングに不要な固定機能操作を 無効にします。たとえば、アプリケーションでライティングやブレンディングが不要な場合は、それ らの機能を無効にしてください。同様に、2Dモデルのみを描画する場合はフォグと深度テストを無効 にします。
ライティングモデルを簡素化する
これは、OpenGL ES 1.1の固定機能ライティングと、OpenGL ES 2.0以降のカスタムシェーダで使用する シェーダベースのライティング演算の、どちらにも適用できるガイダンスです。
● ライティングの使用はできるだけ控え、アプリケーションにとって最もシンプルなタイプのライ ティングを使用します。より多くの演算が必要となるスポットライティングの代わりに、指向性 ライトの使用を検討します。シェーダは、ライティング演算をモデル空間で行う必要がありま す。より複雑なライティングアルゴリズムではなく、よりシンプルなライティング方程式の使用 を検討してください。
● ライティングを事前に計算し、フラグメント処理によってサンプリング可能なテクスチャにカ ラー値を保存します。
タイルベースの遅延レンダリングを効率的に使う
iOSデバイスのGPUはいずれも、タイルベースの遅延レンダリング(TBDR、Tile-Based Deferred Rendering)を実装しています。レンダリングコマンドをハードウェアに送信するためOpenGL ES関数
を呼び出すと、これらのコマンドは、一定量のコマンドが蓄積されるまでバッファに格納されます。タイルベースの遅延レンダリングを効率的に使う