opengl:optimize
差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
opengl:optimize [2014/04/17 02:08] – [演算] oga | opengl:optimize [2014/04/20 04:32] (現在) – [Alpha Test (discard) の是非] oga | ||
---|---|---|---|
行 1: | 行 1: | ||
====== 最適化 ====== | ====== 最適化 ====== | ||
- | GPU にしろ、描画 API にしろ、構造を理解することが最適化の近道 | + | * 構造を理解することが最適化の近道 |
+ | * アプリケーションの高速化ならボトルネックがどこにあるか調べる必要あり | ||
大きく分けて、CPU ボトルネック、GPU ボトルネックの 2種類あります。 | 大きく分けて、CPU ボトルネック、GPU ボトルネックの 2種類あります。 | ||
- | もしパフォーマンスが上がらないなら、まず原因がどこにあるのか調べる必要があります。 | + | もしパフォーマンスが上がらないなら、まずは原因がどこにあるのか調査を行います。 |
- | 原因を調べるためには、GPU メーカーが提供している Profiler などの Tool を用いる方法があります。 | ||
- | これらのツールは使い方や機能がそれぞれ異なっています。 | ||
- | または Fence や TimeStamp などの GPU 同期コマンドを利用して、自分で測定する方法もあります。 | ||
- | ([[http:// | ||
- | 最適化によりどこまで速くなる余地があるのか、GPU/ | + | 最適化によりどこまで速くなる余地があるのか、GPU/ |
- | ハード性能の上限に引っかかっている場合は、アルゴリズムを変える以外に速度を上げる方法はありません。 | + | |
行 29: | 行 26: | ||
* Texture Fetch | * Texture Fetch | ||
* フィルレート制限 | * フィルレート制限 | ||
+ | * メモリ帯域制限 | ||
+ | |||
行 79: | 行 78: | ||
というのも、CPU でレンダリングしていた時代はもちろん、またはコンシューマゲーム機などのゲーム専用ハードでは、 | というのも、CPU でレンダリングしていた時代はもちろん、またはコンシューマゲーム機などのゲーム専用ハードでは、 | ||
Draw API ボトルネックがほとんど存在していなかったからです。 | Draw API ボトルネックがほとんど存在していなかったからです。 | ||
+ | |||
GPU の種類が固定のゲーム専用機では、さまざまな GPU を想定する必要がありません。 | GPU の種類が固定のゲーム専用機では、さまざまな GPU を想定する必要がありません。 | ||
ステート記録時に GPU に適した形に変換してしまうことが可能で、 | ステート記録時に GPU に適した形に変換してしまうことが可能で、 | ||
描画時のステート切り替えも PC と比べると非常に低コストで実現できます。 | 描画時のステート切り替えも PC と比べると非常に低コストで実現できます。 | ||
+ | それどころか、データを出力する時点で GPU Native な Command に事前変換することも可能でよく用いられます。 | ||
+ | ほぼストリームのように、ロードしたあとは GPU に流しこむだけで描画できるわけです。 | ||
+ | PC/ | ||
最適化のためには、Draw Call 回数をできるだけ減らすことが重要となります。 | 最適化のためには、Draw Call 回数をできるだけ減らすことが重要となります。 | ||
一度の Draw Call で出来るだけ多くの描画を行えば効率が上がることがわかっているので、 | 一度の Draw Call で出来るだけ多くの描画を行えば効率が上がることがわかっているので、 | ||
行 94: | 行 97: | ||
AMD の Mantle がその先陣を切っており、MS の DirectX12 が追従しています。 | AMD の Mantle がその先陣を切っており、MS の DirectX12 が追従しています。 | ||
- | この両者とも、大きく削減されるのは CPU 負荷の方であり、GPU に何らかの新機能が増えるわけではありません。 | + | この両者とも、大きく削減されるのは CPU 負荷の方であり、GPU |
+ | 現在発売している GPU がすでに DirectX12 対応を謳っていることからも明らかです。 | ||
この点で、今までのメジャーアップデートとは目的が大きく異なっています。 | この点で、今までのメジャーアップデートとは目的が大きく異なっています。 | ||
行 106: | 行 111: | ||
* GPU へのオフロード | * GPU へのオフロード | ||
- | 等 | + | |
+ | CPU の特性上、ARM Cortex-A8 では SIMD 最適化が劇的な効果をあげていましたが、 | ||
+ | それ以外では Multi core への Thread 化の方が効果を得やすいでしょう。 | ||
+ | |||
+ | Mobile Device では Core 数や GPU 種類を一定に見積もりできないため、 | ||
+ | ゲーム専用機と比べるとぎりぎりまでの最適化はできず、妥協は必要。 | ||
+ | むしろ負荷よりも互換性の方が問題になりがちです。 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== GPU 負荷 ===== | ||
+ | |||
+ | GPU の構造によって特性がかなり異なってきます。 | ||
+ | そのためどの手法を用いた方が良いのか必ずしも最適な方法があるとは限らず、GPU によっては意味が無かったり逆効果に働く可能性もあります。 | ||
+ | |||
+ | |||
+ | |||
+ | ==== 演算精度 ==== | ||
+ | |||
+ | OpenGL ES のシェーダープログラムでは、precision 宣言が可能です。 | ||
+ | 用途に応じて演算精度を適切に変えることができます。 | ||
+ | |||
+ | 演算精度を下げる事による主なメリットは 2点。ただし GPU によって異なります。 | ||
+ | |||
+ | * ALU の演算能力が増える | ||
+ | * レジスタの消費を抑えることでスレッド並列度が上がる | ||
+ | |||
+ | GPU のシェーダー演算能力には限りがあります。 | ||
+ | ピーク性能は ALU の演算 Unit x 動作クロックで求まるので、この範囲でシェーダーの設計をしなければなりません。 | ||
+ | |||
+ | 一部の Mobile 向け GPU では、演算精度を下げることによりトータルの演算能力を増やすことができます。 | ||
+ | CPU で言えば SSE 等 SIMD 命令と同じで、倍精度 (64bit fp) なら 128bit ALU で一度に 2演算ですが、 | ||
+ | 単精度 (32bit fp) なら 4演算が可能になります。 | ||
+ | |||
+ | 同じように GPU によっては、 | ||
+ | highp (32bit fp) では 1演算ですが、mediump 宣言を行うと SIMD で同時に 2演算 (16bit fp) できるものがあります。 | ||
+ | lowp (10bit fixed) も同様です。 | ||
+ | |||
+ | 演算精度を下げることで、シェーダーの実行パフォーマンスが向上する GPU としては | ||
+ | PowerVR SGX, Tegra 2/3/4, Mali-400MP があります。 | ||
+ | |||
+ | 特に PowerVR SGX は ALU の演算能力がボトルネックになりやすく、精度指定によるシェーダーサイクルの削減が全体の描画速度に如実に現れます。 | ||
+ | Tegra や Mali-400 の場合はテンポラリレジスタの削減による効果だと思われます。 | ||
+ | |||
+ | ただし演算精度を下げることでクオリティも下がるので、シェーダー最適化時には用途に合わせた細かいチューニングが必要となります。 | ||
+ | |||
+ | 逆に Adreno は Desktop GPU と同じで常に highp (32bit fp) 演算が用いられており、 | ||
+ | 演算精度を指定しても変化がありません。 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Alpha Test (discard) の是非 ==== | ||
+ | |||
+ | 新しい GPU では、Alpha Test (discard) はパフォーマンスの低下を招く要因であると言われています。 | ||
+ | |||
+ | 例えば PowerVR などの Deferred Rendering (TBDR) との相性が悪くなります。 | ||
+ | PowerVR は先に Depth Buffer を生成しておき、表面の必要なピクセルに対してのみ Pixel Shader (Fragment Shader) を走らせます。 | ||
+ | ポリゴンが重なってもシェーダー負荷が一定以上上がらないので、効率よい描画ができることが特徴です。 | ||
+ | ちょうど Desktop GPU で用いられる Deferred Lighting を、ハードウエアが自動的に行ってくれていることになります。 | ||
+ | ところが、もし Shader に discard 命令が含まれているなら、Shader を実行してみないと正しい Depth Buffer を得ることができません。 | ||
+ | よってポリゴンの重なりを効率良く取り除くことができなくなります。 | ||
+ | |||
+ | 古い GPU アーキテクチャにおいては必ずしも悪い面だけとは限りません。 | ||
+ | discard (texkill) によって早いタイミングで Pixel Shader を終了させることにより、 | ||
+ | 後続のシェーダーの演算や無駄な Texture Fetch を省くことが可能になります。 | ||
+ | Tegra 2/3/4 の ULP GeForce は G70 世代の古い GPU core なので、適切に discard (texkill) を使用した方がシェーダーの実行効率を上げることができると言われています。 | ||
+ | 例えば半透明描画時にテクスチャの Alpha 値が 0 とわかっているならば、カラーの演算結果は最終的に無駄になります。 | ||
+ | カラーを出力しないで、テクスチャを読んだ直後に discard (texkill) してピクセルを捨てる方が都合が良いわけです。 | ||
+ | |||
+ | ただし他の GPU との互換性や今後のことを考えると、使わない方が良いと思われます。 | ||
+ | |||
+ | |||
+ | ==== Vertex Cache と Primitive Type ==== | ||
+ | |||
+ | ==== Tile Base と Framebuffer ==== | ||
opengl/optimize.1397668085.txt.gz · 最終更新: 2014/04/17 02:08 by oga