2/26/2015

[&] WebGL Performance Tuning



( via. Behind the magic of AKQA Winterlands )

#WebGL Performance Tuning

WebGLコンテンツ/プログラムの速度をコツコツと速くするための、
パフォーマンスチューニング観点をまとめました。

まずはプロファイリングが重要。
闇雲にチューニングしても、あまり速くならない場合もあります。
また、最初の設計や、ハードウェア性能を知った上でのデータ量の見積もりも重要です。

■WebGLプロファイリングのコツ

●グラフィックスパイプラインを理解し、どこに時間がかかるか、どこがボトルネックか見極める。
●画面サイズを1/2や1/4にして確かめる(GPU性能か、それ以外が原因か解る)
●目的のハードウェアがどれくらいの数、物量の描画が描けるのか単純なサンプルで限界を測定する。
●機能をON/OFFして確かめる(テクスチャ有り/無しとか、入力操作有り/無しとか)
●JavaScriptが遅い部分と WebGLが遅い部分を切り分ける

■WebGL高速化のコツ:ハードウェアの仕組みを理解して性能をあげる

●CPU-GPU間のやり取りを最小に。事前に計算できることは、できるだけ前処理で計算しておく。
また、GPU側にデータを送り込むような場合は、できるだけまとめて一気に。

●1枚のテクスチャに押し込め、テクスチャコーディネートで使い回す
最近の環境だと、複数テクスチャを bind しておき、切り替えるだけでも高速。
使うたびに毎回読み込んだりするのは極端に効率が落ちる。

●解りやすい結果を得るには Draw Callsを減らす。
むやみに減らすのではなくクオリティとのバランス。減らすとどれくらい速くなるのかを把握しつつ。

●ポリゴンの描き方、描き順を、グラフィックスハードウェアに最適化する。
三角形よりも、四角形が速い環境、または逆の環境もある。
頂点座標の扱いはできるだけまとめてしまう。
連続していないデータでも、ダミーの三角形を挟んで、アレイ化する方法も有効

●WebGL Inspector で繰り返し呼んでいる命令を見つけ削除または、削減につとめる

●WebGLベンチマークで利用するグラフィックスハードウェアの遅い命令、速い命令を把握する

●OpenGL エラーを排除する。デフォルト値が設定されていないとか、範囲外の値を設定したとか、
エラーを皆無にすることで、引っかかりを無くすことができる場合もある。

●WebGL コンフォーマンステストで使えない命令、曖昧な命令を見つけておき、避けるようにする。

●シェーダーはできるだけ分岐判断させない。分岐判断はできるだけ最後に
計算速度の速いシェーダーで代替できないか考える。計算式によるが、単純に短いと速い。
シェーダーの動的コンパイルの時間もあるので、使い回せると速い(と思う。測ってない)。

●ターゲットとなるハードウェアを確認し、EXT命令で活用できるものを探す。
高速化のための拡張命令は積極的に使う。

●GL系、画面データを読み取るのは時間がかかる。
画面のピクセルZ値を取得するなど、get() 系の命令を使うのを控える。
または、ループ外で一気に使うようにする。
ループ内で使うと読むのと書くのと、コンテキストスイッチの切り替えに時間がかかる。

●設定しなくて良いものは、デフォルト値を使う。
何がデフォルト値なのは、決まっているが、まれに初期値が不定なことが仕様の値もあるので注意。

●目標のフレームレートが決まれば、その1フレーム内でどれだけの計算や描画が行えるか計算し、
その秒数内で様々な事象が完結するようにする。30fps 目標であれば、33.3msec 以内。

■WebGLコンテンツの作り方の工夫

●フレームワーク Three.js,GLGE,PhiloGL,SceneJS,SpiderGLは開発速度を上げるけど、
生のOpenGL ES を使うよりは、動作速度は遅くなる。
フレームワーク内部の計算部分など、速度に関するオーバーヘッドもあるので注意して使う。

●テクスチャサイズはクオリティが許せるまで極限まで小さく。
2DのPhotoshop 画面で見ているクオリティと、3D画面内のどこかで使っているテクスチャは
それほど高解像度で無くとも十分な場合がある。

●テクスチャの種類によっては、極限まで圧縮されたJPEGファイルを展開するCPU負荷よりも、
BMPファイルをそのまま使う方が早かったりする場合もある。常に計測。常に臨機応変に。

●テクスチャファイルもヘッダ情報を削除したり、少しでも小さくしておく。便利なツールがいろいろある。

●ハードウェアによってはブレンドが超遅い、並び順序、色順序を考慮しておくと良い。
モデルの描画順序をコントロールしておくのが良い場合もあり。

●古めの環境だと、まれにテクスチャのRGB格納順序で速度が違う環境がある。
考え方としては、画像フォーマットに合わせるのではなく、ハードウェアが最適とするフォーマットに合わせる。

●並行処理、ベクトル演算の考えを行き渡らせる。一緒にできることはまとめて扱う

●イベントループを工夫
requestAnimationFrame() を使う。setInterval() は止める。

●数値計算的なものはJavaScript でやらず、WebGL/GPUに任せる

●模様的なテクスチャであれば、画像よりも、シェーダー生成で。圧倒的にサイズが違う。

●最近は自由なサイズのテクスチャが使えるが、ハードウェア最適化を考えると、
いぜん正方形テクスチャの方が速い場合が多い。常に2のベキ状サイズで考える。

●画面解像度が極端に大きい時はSVGの方がいい。WebGL 以外で実装した方が良い場合もあり。

●視点から近い時には細かく、遠い時には荒く LOD(Level of Detail) という考えは基本。

■WebGL環境の工夫

●ハードウェア環境の OS やグラフィックスドライバを可能な限り最新なものにしておく。
またOSやドライバの環境で、バグや性能が異なることを把握しておく

●画面密度の高い Retina ディスプレイの場合は、
50%サイズで描画して、HTMLで2倍拡大表示しても十分な場合も。

●環境が違うと動かないことを常に考慮しておく。
ブラウザの種類、バージョン、WebGLの設定のON/OFF,
グラフィックスハードウェアのメーカー、チップの違い、OSの違い、メモリ量の違い
シェーダーの複雑度、ドライバの実装の違い、対応しているテクスチャ圧縮フォーマットの違い

●なにかバグを見つけたら、Chrome も WebGL も、NVIDIA,ATI,Intel もどんどんバグレポートすると治るのが早いよ!

●最終ターゲットの主流がモバイル(iOS, Android)の場合は、
パソコン上で開発すると、リッチコンテンツになりすぎて、それを削ってモバイル用にするのは辛いので、
最初から、モバイルターゲットの物量、質感に調整した上で、出来上がったらデータ量を増やしてパソコン用にすると良い。
(AKQA の Winterlands snow.akqa.com がとてもいい例だと思う)

■WebGL関連の役立つツール

●WebGL Texture Tester
http://toji.github.io/texture-tester/
対応しているテクスチャ圧縮方式を一気に確認する方法。画質も確認できます。
WebP, DXT1, DXT2, DXT5, PVRTC, ATC, ETC1



●WebGL Inspector
http://benvanik.github.io/WebGL-Inspector/
Webインスペクターの WebGL 版。必須ツール。
Chrome Canvas Inspector も活用できます。
http://www.html5rocks.com/en/tutorials/canvas/inspection/

●Google Web Tracing Framework
パフォーマンス状況をトレースできるツール
http://google.github.io/tracing-framework/

●WebGL Report
http://webglreport.com/
ブラウザ環境、グラフィックスハードウェア環境を見て、
各種最大値、使える拡張命令などを一気に調べられるツール



●Chrome about:tracing
Chrome に "about:tracing" と書き込み、メータをON にするだけで、
画面右上にパフォーマンスメーターが表示されるように。
FPSやGPUメモリ消費量などを逐一チェックできる。
ただし、WebGL以外の普通の描画でも GPU は使われている。
http://www.html5rocks.com/en/tutorials/games/abouttracing/



■WebGL関連の役立つ動画資料

GDC 2012: From Console to Chrome:コンソールゲームをChrome上で実現!


Google I/O 2011: WebGL Techniques and Performance : 内容はちょっと古いけど基本を知るには良い。



「早すぎる最適化は諸悪の根源である」ドナルド・クヌース
「スマートなデータを使う、つまらないコードを書け」ロブ・パイク