モバイル gpu でのハイエンド レンダリングエンジン開発事例

146
モモモモ GPU モモモモモモモ モモモモモモモモモモモモモモ モモ モモモモモモ モモモモモ () モモモモ モモモモ Elliott Davis

Upload: jolene-riley

Post on 15-Mar-2016

68 views

Category:

Documents


1 download

DESCRIPTION

モバイル GPU でのハイエンド レンダリングエンジン開発事例. (株)トライエース 研究開発部 永野和博 大嶋貴史  Elliott Davis. コンテンツ. 開発を始める前に 実装 最適化手法. 開発を始める前に 達成目標 開発環境 スケーラビリティを意識する 具体的な作業箇所. コンテンツ. 達成目標. 達成目標 自社開発の PS3, XBOX360 等スマートフォンよりも高性能な機器で動作する , マルチプラットフォームエンジンをスマートフォン上でも動作するようにポーティングを行う 対応プラットフォーム iOS5.0 以上 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: モバイル GPU でのハイエンド レンダリングエンジン開発事例

モバイル GPU でのハイエンドレンダリングエンジン開発事例

(株)トライエース 研究開発部永野和博 大嶋貴史  Elliott Davis

Page 2: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 開発を始める前に• 実装• 最適化手法

Page 3: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 開発を始める前に– 達成目標 – 開発環境– スケーラビリティを意識する– 具体的な作業箇所

Page 4: モバイル GPU でのハイエンド レンダリングエンジン開発事例

達成目標

• 達成目標– 自社開発の PS3, XBOX360 等スマートフォ

ンよりも高性能な機器で動作する , マルチプラットフォームエンジンをスマートフォン上でも動作するようにポーティングを行う

• 対応プラットフォーム– iOS5.0 以上 – Android 2.3 以上

Page 5: モバイル GPU でのハイエンド レンダリングエンジン開発事例

達成目標

検証 GPU の種類Vendor Imagination Technologies Qualcomm NVIDIA ARM

PoweVR SGX 540 (200MHz) Adreno 205 Tegra 2 Mali-400 MPPoweVR SGX 540 (384MHz) Adreno 220 Tegra 3 Mali-T604

PoweVR SGX 535 Adreno 225 Tegra 4PoweVR SGX 543MP2 Adreno 320PoweVR SGX 543MP4 Adreno 330PoweVR SGX 554MP4

GPU

上記の GPU の種類だけではなく , 更に CPU/OS の組み合わせがあるため対応すべきデバイスの種類は数え切れず , これからも増え続けていく

iOS Device

Android

Page 6: モバイル GPU でのハイエンド レンダリングエンジン開発事例

達成目標

検証 GPU の種類

上記の GPU の種類だけではなく , 更に CPU/OS の組み合わせがあるため対応すべきデバイスの種類は数え切れず , これからも増え続けていく

iOS Device

Android

今後の事を見据えたしっかりとした事前準備はとても大切

Vendor Imagination Technologies Qualcomm NVIDIA ARMPoweVR SGX 540 (200MHz) Adreno 205 Tegra 2 Mali-400 MPPoweVR SGX 540 (384MHz) Adreno 220 Tegra 3 Mali-T604

PoweVR SGX 535 Adreno 225 Tegra 4PoweVR SGX 543MP2 Adreno 320PoweVR SGX 543MP4 Adreno 330PoweVR SGX 554MP4

GPU

Page 7: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 開発を始める前に– 達成目標 – 開発環境– スケーラビリティを意識する– 具体的な作業箇所

Page 8: モバイル GPU でのハイエンド レンダリングエンジン開発事例

IDE 言語 グラフィックスAPI その他

iOS Xcode Objective C++ OpenGL ES 2.0Android Eclipse C++ (一部J ava) OpenGL ES 2.0 Native Activity

開発環境

• 何を用いて開発するか?

Page 9: モバイル GPU でのハイエンド レンダリングエンジン開発事例

IDE 言語 グラフィックスAPI その他

iOS Xcode Objective C++ OpenGL ES 2.0Android Eclipse C++ (一部J ava) OpenGL ES 2.0 Native Activity

開発環境

• Xcode 上で問題なくデバッグできる

• 端末内の CPU/GPU の比較的統一されている

• こちらの方が開発は容易と予想

• 何を用いて開発するか?

Page 10: モバイル GPU でのハイエンド レンダリングエンジン開発事例

IDE 言語 グラフィックスAPI その他

iOS Xcode Objective C++ OpenGL ES 2.0Android Eclipse C++ (一部J ava) OpenGL ES 2.0 Native Activity

開発環境

• Eclipse 上でデバッグが困難– ブレイクポイントに止まらないことがある

– C++ を用いない箇所ではブレイクに止まる

• CPU/GPU のバリエーションが多すぎる

• こちらの開発はかなり大変

• 何を用いて開発するか?

Page 11: モバイル GPU でのハイエンド レンダリングエンジン開発事例

開発環境

• 開発スタイル– iOS の開発を先行して行い Android に移植– iOS 側で主要な実装と不具合を除去– Android 側は端末毎の固有の問題解決に注力

Page 12: モバイル GPU でのハイエンド レンダリングエンジン開発事例

開発環境

• 現在の EGL と GLES2 の状態を出力する関数を作る– 特に Android に有用

• 妥当性 : – glIsOOOO()– glValidateProgram()– glCheckFramebufferStatus()

• エラー : – glGetError()– eglGetError()

• エラーを出力する際は , 現在のスレッド情報も含める– ID 又は名前– GLES2 のコンテキスト ID

Page 13: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 開発を始める前に– 達成目標 – 開発環境– スケーラビリティを意識する– 具体的な作業箇所

Page 14: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• どれくらいの性能差があるのだろう?– 新製品発売のスパンが短い

• 市場はローエンド機とハイエンド機が混在している

– ローエンドとハイエンドの性能差は 10 倍~15 倍程度はある

スケーラビリティを意識する

Page 15: モバイル GPU でのハイエンド レンダリングエンジン開発事例

ローエンド機に合わせてエンジンを作成

• どれくらいの性能差があるのだろう?– 新製品発売のスパンが短い

• 市場はローエンド機とハイエンド機が混在している

– ローエンドとハイエンドの性能差は 10 倍~15 倍程度はある

スケーラビリティを意識する

Page 16: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• どれくらいの性能差があるのだろう?– 新製品発売のスパンが短い

• 市場はローエンド機とハイエンド機が混在している

– ローエンドとハイエンドの性能差は 10 倍~15 倍程度はある

スケーラビリティを意識する

ローエンド機に合わせてエンジンを作成

可能な限り端末毎の最大性能を出させて良い映像を出す

Page 17: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 方法– 端末の性能毎にポストプロセスの設定を調整

する• ブルームの解像度

スケーラビリティを意識する

Page 18: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 方法– 端末の性能毎にポストプロセスの設定を調整

する• ブルームの解像度

– 端末の性能毎にシェーダの複雑さを調整する• ライト個数• ライティングをフラグメントシェーダからバー

テックスシェーダへ

• など

スケーラビリティを意識する

Page 19: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 方法– 端末の性能毎にポストプロセスの設定を調整

する• ブルームの解像度

– 端末の性能毎にシェーダの複雑さを調整する• ライト個数• ライティングをフラグメントシェーダからバー

テックスシェーダへ

• など– 端末の性能毎にランタイム内にてフロント

バッファ , バックバッファ解像度を調整できるようにする

スケーラビリティを意識する

Page 20: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• どのようにして性能値を導くか?– あらかじめ主要な端末を調査し , ある程度

テーブル化しておきそこから外れるものは端末のデバイス情報とテーブルを参考に計算で求める

–初期化時にベンチマークを走らせて取得する

スケーラビリティを意識する

Page 21: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• パフォーマンス変動をもたらす特殊な要因–温度変化

• 端末の温度上昇に連動して CPU/GPU のクロックが調整されている

–節電モード• リフレッシュレートが半分に抑制される

– BlueTooth• 原因は不明だが OFF にすることによりパフォー

マンスが劇的に改善するケースがあった

スケーラビリティを意識する

Page 22: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 開発を始める前に– 達成目標 – 開発環境– スケーラビリティを意識する– 具体的な作業箇所

Page 23: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 当初の予想–ネイティブ API にかかわる箇所とシェーダに

関する修正を行う程度で問題ない– iOS から Android への移植もそれほど困難で

はない

具体的な作業箇所

Page 24: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 当初の予想–ネイティブ API にかかわる箇所とシェーダに

関する修正を行う程度で問題ない– iOS から Android への移植もそれほど困難で

はない

当初の予想に反し数々の問題が発生

具体的な作業箇所

Page 25: モバイル GPU でのハイエンド レンダリングエンジン開発事例

具体的な作業箇所

N+1 N+2

N

N+1 N+2

N+1

VSync (垂直同期)

N+3

VSync (垂直同期)

VSync (垂直同期)

N+2

N+3メインスレッド

ワーカースレッド 1

レンダースレッド

… …N+1 N+2 N+3ワーカースレッ

ド N

• エンジン内部の動作

Page 26: モバイル GPU でのハイエンド レンダリングエンジン開発事例

具体的な作業箇所

PrepareForRendering RenderContext生成

(Shader, Texture, State, etc)

Task処理

PreRender

WaitDraw

VSync

Dynamics, Collision, Animation

その他

Matrix, Culling

その他レンダリング準備

… DrawCall

Flush

Swap

メインスレッド

ワーカースレッド

レンダースレッド

Page 27: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 変更が必要だった箇所

– 画面更新のタイミング端末毎に異なっている事が判明

具体的な作業箇所

Page 28: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 変更が必要だった箇所

– 画面更新のタイミング端末毎に異なっている事が判明

– マルチスレッドレンダリングレンダリングコンテキストの問題

具体的な作業箇所

Page 29: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 変更が必要だった箇所

– 画面更新のタイミング端末毎に異なっている事が判明

– マルチスレッドレンダリングレンダリングコンテキストの問題

– シェーダ関連GPU に依存する問題

具体的な作業箇所

Page 30: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 変更が必要だった箇所

– 画面更新のタイミング端末毎に異なっている事が判明

– マルチスレッドレンダリング

レンダリングコンテキストの問題

– シェーダ関連GPU に依存する問題

– レンダーターゲット関連GPU, 端末種に依存する問題

具体的な作業箇所

Page 31: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• 変更が必要だった箇所

– 画面更新のタイミング端末毎に異なっている事が判明

– マルチスレッドレンダリング

レンダリングコンテキストの問題

– シェーダ関連GPU に依存する問題

– レンダーターゲット関連GPU, 端末種に依存する問題

– 最適化GPU 毎に適した方法

具体的な作業箇所

Page 32: モバイル GPU でのハイエンド レンダリングエンジン開発事例

実装

Page 33: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 実装– リフレッシュレート– マルチスレッドレンダリング– GPU 毎の Uniforms– フレームバッファ

Page 34: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

• 画面更新のタイミング– VSync(垂直同期 ) のシグナルを利用

Page 35: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

• 画面更新のタイミング– VSync(垂直同期 ) のシグナルを利用

ここで問題発生 !!

Page 36: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

• 問題の概要– Vsync(垂直同期 ) のシグナルが取得できな

い• Android 4.0 以下のみの問題• iOS デバイスでは問題ない

– Android ではリフレッシュレートが端末毎に変化

–アニメーション等アセットが基準フレームレートに基づいて作成されている場合 , 再生速度が変化してしまう

リフレッシュレート1秒間に画面の更新が何回行われるかの事で単位はHz

Page 37: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

• リフレッシュレートを確認– JNI(Java Native Interface) を用いて端末に

問い合わせる– 自分で計測する

Page 38: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• リフレッシュレートを確認– JNI(Java Native Interface) を用いて端末に

問い合わせる– 自分で計測する

public float GetRefreshRate(){WindowManager windowManager = getWindowManager();Display display = windowManager.getDefaultDisplay();return display.getRefreshRate();

}

JNIEnv* pEnv = GetJNIEnv();Android_app* pApp = GetAndroidApp();jmethodID ID = pEnv->GetMethodID("GetRefreshRate", "()F");float fRefreshRate =(float)pEnv->CallFloatMethod(pApp()->activity->clazz, mID);

リフレッシュレート

C++ 側

Java 側

Page 39: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

uPrevTime = getCurrentTime();for( int i = 0; i < COUNT; i++ ) { glClear( GL_DEPTH_BUFFER_BIT|

     GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT   );

eglSwapBuffers(EGLData.display,EGLData.surface);}uAfterTime = getCurrentTime();uTotal = AfterTime – uPrevTime; sRefreshRate = uTotal / COUNT;

• リフレッシュレートを確認– JNI(Java Native Interface) を用いて端末に

問い合わせる– 自分で計測する

Page 40: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

問い合わせ値 68Hz 60.382Hz 55Hz 60Hz 60Hz 60.382Hz

計測値 53Hz 59Hz 57Hz 61Hz 59Hz 30Hz

GalaxyS2(ISW11SC)節電モード

GalaxyS(SC-02B)

Arrowsμ(F-07D)

MediasLTE(N-04D)

GalaxyS2(ISW11SC)

ArrowsZ(ISW13F)

計測値と問い合わせた値が一致しない

• 取得結果

Page 41: モバイル GPU でのハイエンド レンダリングエンジン開発事例

以前の実装

• 基準フレームレートをもとにした可変フレームレート方式–アプリケーション起動時 , 基準フレームレー

トを設定– フレームレートは基準フレームレートの整数分の1で可変

• 基準フレームレートが 30 の時– 30, 15, 10, 7.5… の範囲で可変

Page 42: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

• 解決策–完全可変フレームレート方式

• 1フレームにかかった時間を計測し , その時間を用いてアニメーションを再生

– フレームドロップ方式• 1フレーム時間と基準フレーム時間の差分を蓄積

し , 差分が基準フレーム分蓄積した際にフレームドロップを行う

Page 43: モバイル GPU でのハイエンド レンダリングエンジン開発事例

リフレッシュレート

• 完全可変フレームレート方式–長所

• アニメーションが滑らか– 短所

• アセットが可変フレームレートを想定していない場合想定どおりの再生ができない

• フレームドロップ方式–長所

• アセットが基準フレームレートに基づいて作成されていても想定どおりの時間で再生可能

– 短所• アニメーションが滑らかではない

Page 44: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 実装– リフレッシュレート– マルチスレッドレンダリング– GPU 毎の Uniforms– フレームバッファ

Page 45: モバイル GPU でのハイエンド レンダリングエンジン開発事例

マルチスレッドレンダリング

• 概要1.複数の GLES2 のコンテキスト2.パフォーマンス調査

Page 46: モバイル GPU でのハイエンド レンダリングエンジン開発事例

EGL の仕様

• 複数のコンテキストが作成可能• 各スレッド間でどのコンテキストも使用可

能• 作成したリソースは共有可能

– テクスチャ– レンダーバッファ– シェーダ– バーテックスバッファ– インデックスバッファ– 等

Page 47: モバイル GPU でのハイエンド レンダリングエンジン開発事例

一般の実装

シェーダコンパイル

レンダー

ゲームオブジェクト更新

• コンテキストが必要なスレッド

Page 48: モバイル GPU でのハイエンド レンダリングエンジン開発事例

iOS での最初の実装• 複数のコンテキスト

を使用

 

• コンテキストが必要なスレッド

シェーダコンパイル

レンダー

ゲームオブジェクト更新

アプリメイン

Page 49: モバイル GPU でのハイエンド レンダリングエンジン開発事例

iOS での最初の実装• 複数のコンテキスト

を使用

• EAGLContext のrenderbufferStorage() を呼ぶタイミング問題の影響でアプリメインスレッドで呼ぶ

 

• コンテキストが必要なスレッド

シェーダコンパイル

レンダー

ゲームオブジェクト更新

アプリメイン

Page 50: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装

• iOS と同様に複数のコンテキストを使おうとしたが

• いくつかの Android端末はコンテキストを一つしか使えない !

• このままではマルチスレッドレンダリング不可能

シェーダコンパイル

レンダー

ゲームオブジェクト更新

• コンテキストが必要なスレッド

Page 51: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装

• いくつかの Android端末はコンテキストを一つしか使えない !

• このままではマルチスレッドレンダリング不可能

• スレッド:

シェーダコンパイル

レンダー

ゲームオブジェクト更新

使えない

Page 52: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装 ー 解決方法

シェーダコンパイル

ゲームオブジェクト更新

• スレッド:

レンダー

使えない

Page 53: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装 ー 解決方法

1. コンテキストをレンダースレッドにバインドする

シェーダコンパイル

レンダー

ゲームオブジェクト更新

• スレッド:コンテキストが必要

使えない

Page 54: モバイル GPU でのハイエンド レンダリングエンジン開発事例

レンダー

シェーダコンパイル

Android の実装 ー 解決方法

1. コンテキストをレンダースレッドにバインドする

2. シェーダコンパイルをレンダースレッドで行う

シェーダコンパイル

レンダー

ゲームオブジェクト更新

• スレッド:コンテキストが必要

使えない

Page 55: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装 ー 解決方法

1. コンテキストをレンダースレッドにバインドする

2. シェーダコンパイルをレンダースレッドで行う

3. GLES2 リソースのラッパークラスの実装を変更

レンダー

シェーダコンパイル

• スレッド:コンテキストが必要使える使えない

ゲームオブジェクト更新

Page 56: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装 ー 解決方法

• スレッド:コンテキストが必要使える使えない

レンダー

シェーダコンパイル

3. GLES2 リソースのラッパークラスの実装を変更

• リソースを作成や変更の場合– GLES2 関数を呼ばな

い– その為のデータを保持

ゲームオブジェクト更新

Page 57: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の実装 ー 解決方法

レンダー

シェーダコンパイル

• スレッド:コンテキストが必要使える使えない

3. GLES2 リソースのラッパークラスの実装を変更

• GLES2 リソースを使う前に– 保持したデータを

GLES2 関数に渡して、リソースを作成や更新• 必要な時だけ

ゲームオブジェクト更新

Page 58: モバイル GPU でのハイエンド レンダリングエンジン開発事例

最終結果

レンダー

シェーダコンパイル シェーダコンパイル

レンダー

ゲームオブジェクト更新

アプリメイン

シェーダコンパイル

レンダー

アプリメイン

シェーダコンパイル

レンダー

アプリメイン

シェーダコンパイル

レンダー

シェーダコンパイル

アプリメイン

レンダー

シェーダコンパイル

コンテキストが必要 使える 使えない

Android iOS

ゲームオブジェクト更新

Page 59: モバイル GPU でのハイエンド レンダリングエンジン開発事例

マルチスレッドレンダリング

• 概要1.複数の GLES2 のコンテキスト2.パフォーマンス調査

Page 60: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• CPU処理が重いシーンで測定– 最大パーティクル数を高くする–放出率を高くする– パーティクルデータの更新:

• ワーカースレッドで行う

• レンダースレッドで行わない

パフォーマンス

Page 61: モバイル GPU でのハイエンド レンダリングエンジン開発事例

20

34

18

43.5

0

10

20

30

40

50

Xperia SO- 02C( )シングルコア

MEDIAS N- 04D( )マルチコア

iPhone4( )シングルコア

iPhone4S( )マルチコア

レンダースレッド無し レンダースレッド有り

パフォーマンス結果

fps

fps

Page 62: モバイル GPU でのハイエンド レンダリングエンジン開発事例

20

34

18

43.5

0

10

20

30

40

50

Xperia SO- 02C( )シングルコア

MEDIAS N- 04D( )マルチコア

iPhone4( )シングルコア

iPhone4S( )マルチコア

レンダースレッド無し レンダースレッド有り

パフォーマンス結果

マルチコアで高速化に成功fps

fps

Page 63: モバイル GPU でのハイエンド レンダリングエンジン開発事例

20

34

18

43.5

0

10

20

30

40

50

Xperia SO- 02C( )シングルコア

MEDIAS N- 04D( )マルチコア

iPhone4( )シングルコア

iPhone4S( )マルチコア

レンダースレッド無し レンダースレッド有り

パフォーマンス結果

シングルコアでも速度向上に成功• GLES2 の API 内で発生するブロッキング中にメインスレッドへスイッチしたため , その分速度を向上させることができている模様

fps

fps

Page 64: モバイル GPU でのハイエンド レンダリングエンジン開発事例

20

34

18

43.5

0

10

20

30

40

50

Xperia SO- 02C( )シングルコア

MEDIAS N- 04D( )マルチコア

iPhone4( )シングルコア

iPhone4S( )マルチコア

レンダースレッド無し レンダースレッド有り

パフォーマンス結果

シングルコアでは速度が多少減少• スレッド切り替えコストが高く、速度が上がらない

fps

fps

Page 65: モバイル GPU でのハイエンド レンダリングエンジン開発事例

20

34

18

43.5

0

10

20

30

40

50

Xperia SO- 02C( )シングルコア

MEDIAS N- 04D( )マルチコア

iPhone4( )シングルコア

iPhone4S( )マルチコア

レンダースレッド無し レンダースレッド有り

パフォーマンス結果

シングルコアでは端末によってメリット又は

デメリットがある• 解決方法:ランタイム中に端末毎にレン

ダースレッドを使用するかどうかを決定

fps

fps

Page 66: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• ドローコール数が多いシーンで測定– 複数のボックスを配置– 先程と同じく CPU負荷を意図的に高くして

おく

パフォーマンス

Page 67: モバイル GPU でのハイエンド レンダリングエンジン開発事例

19

28

15

35.5

0

10

20

30

40

50

Xperia SO- 02C(シングルコア)

MEDIAS N- 04D(マルチコア)

iPhone4(シングルコア)

iPhone4S(マルチコア)

レンダースレッド無し レンダースレッド有り

パフォーマンス結果fps

fps

Page 68: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 実装– リフレッシュレート– マルチスレッドレンダリング– GPU 毎の Uniforms– フレームバッファ

Page 69: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Uniform とは ?• シェーダで利用される定数データ

• HLSL の場合、シェーダコンスタントと呼ばれる

Page 70: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• glGetActiveUniform ()で情報が取得– 名前–配列サイズ–型

ここで問題発生

Uniform とは ?

Page 71: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• glGetActiveUniform ()で情報が取得– 名前–配列サイズ–型

ここで問題発生

Uniform とは ?

Page 72: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• glGetActiveUniform ()で情報が取得– 名前–配列サイズ–型

GLES2 の仕様によるとGPU によって変化しない

問題の概要

Page 73: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• glGetActiveUniform ()で情報が取得– 名前–配列サイズ–型

実際には変化してしまう

問題の概要

Page 74: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• シェーダ内に構造体を作成• 構造体内に配列型のメンバがある• それを uniform データとして用いた時

struct mat3x4{

vec4 highp m[3]; };       uniform mat3x4 cmWorld;

実例1

Page 75: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• シェーダ内に構造体を作成• 構造体内に配列型のメンバがある• それを uniform データとして用いた時

struct mat3x4{

vec4 highp m[3]; };       uniform mat3x4 cmWorld;

実例1

Page 76: モバイル GPU でのハイエンド レンダリングエンジン開発事例

struct mat3x4{

vec4 highp m[3]; };       uniform mat3x4 cmWorld;

• シェーダ内に構造体を作成• 構造体内に配列型のメンバがある• それを uniform として用いた時

実例1

Page 77: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 配列サイズ 名前 配列サイズcmWorld.m[0] 3 cmWorld.m[0] 3

cmWorld.m[1] 2cmWorld.m[2] 1

iOS / Adreno205/ Tegra3端末 Adreno220/ 225/ 320

struct mat3x4{ vec4 highp m[3]; };  uniform mat3x4 cmWorld;

実例1の取得結果

Page 78: モバイル GPU でのハイエンド レンダリングエンジン開発事例

GLES2 の仕様と一致

名前1つに、配列サイズ=3

名前 配列サイズ 名前 配列サイズcmWorld.m[0] 3 cmWorld.m[0] 3

cmWorld.m[1] 2cmWorld.m[2] 1

iOS / Adreno205/ Tegra3端末 Adreno220/ 225/ 320

実例1の取得結果

struct mat3x4{ vec4 highp m[3]; };  uniform mat3x4 cmWorld;

Page 79: モバイル GPU でのハイエンド レンダリングエンジン開発事例

特殊

名前3つに、それぞれにデクリメントされた配列サイズ

特殊

名前 配列サイズ 名前 配列サイズcmWorld.m[0] 3 cmWorld.m[0] 3

cmWorld.m[1] 2cmWorld.m[2] 1

iOS / Adreno205/ Tegra3端末 Adreno220/ 225/ 320

実例1の取得結果

struct mat3x4{ vec4 highp m[3]; };  uniform mat3x4 cmWorld;

Page 80: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 配列サイズ 名前 配列サイズcmWorld.m[0] 3 cmWorld.m[0] 3

cmWorld.m[1] 2cmWorld.m[2] 1

iOS / Adreno205/ Tegra3端末 Adreno220/ 225/ 320

配列サイズとは

struct mat3x4{ vec4 highp m[3]; };  uniform mat3x4 cmWorld;

• 取得した配列サイズはいつも– X 変数の宣言と同じ– O シェーダ内に使用している要素だけ

Page 81: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 使用中の配列サイズ 名前 使用中の配列サイズcmWorld.m[0] 1~3 cmWorld.m[0] 1~3

cmWorld.m[1] 1~2cmWorld.m[2] 1

iOS / Adreno205/ Tegra3端末 Adreno220/ 225/ 320

配列サイズ → 使用中の配列サイズ

struct mat3x4{ vec4 highp m[3]; };  uniform mat3x4 cmWorld;

配列サイズとは

Page 82: モバイル GPU でのハイエンド レンダリングエンジン開発事例

実例2

• テクスチャサンプラ配列のみ• 構造体と無関係

uniform vec4 vCoef[4]uniform sampler2D asTexStage[16];

Page 83: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 使用中の配列サイズ 名前 使用中の配列サイズvCoef[0] 1~4* vCoef[0] 1~4*asTexStage[0] 1~16* asTexStage[0] 1

asTexStage[1] 1…asTexStage[15]** 1

iOS端末/Adreno 205/Tegra 3 Adreno 220/225/320

• テクスチャサンプラ配列のみ• 構造体と無関係

実例2の取得結果

• テクスチャサンプラ配列のみ• 構造体と無関係

uniform vec4 vCoef[4]uniform sampler2D asTexStage[16];

• テクスチャサンプラ配列のみ• 構造体と無関係

Page 84: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 使用中の配列サイズ 名前 使用中の配列サイズvCoef[0] 1~4* vCoef[0] 1~4*asTexStage[0] 1~16* asTexStage[0] 1

asTexStage[1] 1…asTexStage[15]** 1

iOS端末/Adreno 205/Tegra 3 Adreno 220/225/320

* 名前1つにつき使用中の配列サイズが一致GLES2 の仕様と一致

実例2の取得結果

• テクスチャサンプラ配列のみ• 構造体と無関係

uniform vec4 vCoef[4]uniform sampler2D asTexStage[16];

Page 85: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 使用中の配列サイズ 名前 使用中の配列サイズvCoef[0] 1~4* vCoef[0] 1~4*asTexStage[0] 1~16* asTexStage[0] 1

asTexStage[1] 1…asTexStage[15]** 1

iOS端末/Adreno 205/Tegra 3 Adreno 220/225/320

** 名前の数は実際に使用されている sampler2D 数になり、

全ての配列サイズが1になる

特殊

実例2の取得結果

• テクスチャサンプラ配列のみ• 構造体と無関係

uniform vec4 vCoef[4]uniform sampler2D asTexStage[16];

Page 86: モバイル GPU でのハイエンド レンダリングエンジン開発事例

実例3

uniform vec4 vCoef[4]uniform sampler2D asTexStage[16];uniform int aInteger[16];uniform bool aBool[16];

• 配列を使う• 型と無関係• 構造体と無関係

Page 87: モバイル GPU でのハイエンド レンダリングエンジン開発事例

名前 使用中の配列サイズ 名前 使用中の配列サイズvCoef[0] 1~4* vCoef[0] 4asTexStage[0] 1~16* asTexStage[0] 16aInteger[0] 1~16* aInteger[0] 16aBool[0] 1~16* aBool[0] 16

iOS端末/Adreno 205/Tegra 3 Mali-400 MP

シェーダ内で全ての要素を使用してなくても配列の最大要素数が返ってくる

• 配列を使う• 型と無関係• 構造体と無関係

特殊

実例3の取得結果

uniform vec4 vCoef[4]uniform sampler2D asTexStage[16];uniform int aInteger[16];uniform bool aBool[16];

Page 88: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• Uniform処理に合わせて

– シェーダ内の uniform宣言を変更• 構造体を利用しない• テクスチャサンプラの配列を利用しない

– ランタイムで取得した uniform 情報の違いを考慮

解決方法

Page 89: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• Uniform処理に合わせて

– シェーダ内の uniform宣言を変更• 構造体を利用しない• テクスチャサンプラの配列を利用しない

– ランタイムで取得した uniform 情報の違いを考慮

解決方法

Page 90: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 実装– リフレッシュレート– マルチスレッドレンダリング– GPU 毎の Uniforms– フレームバッファ

Page 91: モバイル GPU でのハイエンド レンダリングエンジン開発事例

フレームバッファ

• 概要– フロントバッファのスワップの最適化– レンダターゲットの最適化

Page 92: モバイル GPU でのハイエンド レンダリングエンジン開発事例

スワップの内部動作

1. フロントバッファのカラーを端末の画面に表示

2. EGL の設定によりスワップ後のフロントバッファのカラーの挙動が変化

• 保持する (変わらない)• 保持しない (壊れているか変えられている可能

性あり)

上記の設定はデフォルトが GPU と OS に依存

Page 93: モバイル GPU でのハイエンド レンダリングエンジン開発事例

スワップの内部動作

1. フロントバッファのカラーを端末の画面に表示

2. EGL の設定によりスワップ後のフロントバッファのカラーの挙動が変化

• 保持する (変わらない)• 保持しない (壊れているか変えられている可能

性あり)

上記の設定はデフォルト値がGPU と OS に依存

Page 94: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• カラーバッファを保持しない方が速い– 多くのアプリは画面全体をフレーム毎に描画するの

でカラーバッファを保存しなくても良い

• デフォルト設定が「保持」の GPU を「保持しない」ように変更すれば最適化が測れる

• 概要– 設定のデフォルト値と変更仕方の紹介– パフォーマンスの結果

スワップの内部動作

Page 95: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• カラーバッファを保持しない方が速い– 多くのアプリは画面全体をフレーム毎に描画するの

でカラーバッファを保存しなくても良い

• デフォルト設定が「保持」の GPU を「保持しない」ように変更すれば最適化が図れる

• 概要– 設定のデフォルト値と変更仕方の紹介– パフォーマンスの結果

スワップの内部動作

Page 96: モバイル GPU でのハイエンド レンダリングエンジン開発事例

iOS の場合

• kEAGLDrawablePropertyRetainedBacking• YES  = 保持する• NO   = 保持しない

• デフォルト値 = NO

Page 97: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android の場合  (EGL1.4 以上 )• eglSurfaceAttrib( EGL_SWAP_BEHAVIOR, EGL_BUFFER_*** )

– EGL_BUFFER_DESTROYED  = 保持しない– EGL_BUFFER_PRESERVED  = 保持する

• デフォルト値は GPU 毎に異なる

• EGL_SWAP_BEHAVIOR が設定できないことがある– EGL 1.4 以上が必要

• 公式には NDK r5 以上でサポート

– EGL仕様によると EGL Surface のコンフィギュレーションを作る時にEGL_SWAP_BEHAVIOR_PRESERVED_BIT が必要

Page 98: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• eglSurfaceAttrib( EGL_SWAP_BEHAVIOR, EGL_BUFFER_*** )– EGL_BUFFER_DESTROYED  = 保持しない– EGL_BUFFER_PRESERVED  = 保持する

• デフォルト値は GPU 毎に異なる

端末名 端末ID GPU EGL_SWAP_BEHAVIORデフォルト値

GALAXY S SC-02B Power VR SGX 540 200MHzAQUOS PHONE SH06-D Power VR SGX 540 384MHzARROWS μ F-07D Adreno 205Xperia SO-02E Adreno 320GALAXY S II WiMAX ISW11SC Mali-400 MPGALAXY S II LTE SC-03D Adreno 220ARROWS Z ISW13F NVIDIA Tegra 3

EGL_BUFFER_DESTROYED

EGL_BUFFER_PRESERVED

Android の場合  (EGL1.4 以上 )

Page 99: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• EGL_SWAP_BEHAVIOR が設定できないことがある– EGL 1.4 以上が必要

• 公式には NDK r5 以上でサポート– OS 2.3 と同時に出た

– EGL仕様によると EGL Surface のコンフィギュレーションに EGL_SWAP_BEHAVIOR_PRESERVED_BIT が必要

• ビットフラッグ設定の意味は– 設定している =  EGL_SWAP_BEHAVIOR が変更可能– 設定しない =  EGL_SWAP_BEHAVIOR が変更不可能

Android の場合  (EGL1.4 以上 )

Page 100: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• EGL_SWAP_BEHAVIOR が設定できないことがある– EGL 1.4 以上が必要

• 公式には NDK r5 以上でサポート– OS 2.3 と同時に出た

– EGL仕様によると EGL Surface のコンフィギュレーションに EGL_SWAP_BEHAVIOR_PRESERVED_BIT が必要

• ビットフラグ設定の意味は– 設定している =  EGL_SWAP_BEHAVIOR が変更可能– 設定しない =  EGL_SWAP_BEHAVIOR が変更不可

Android の場合  (EGL1.4 以上 )

Page 101: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• PowerVR SGX 540 は「不可能」でも EGL_SWAP_BEHAVIOR の値が変更できる– EGL の仕様の例外

EGL_SWAP_BEHAVIOR_PRESERVED_BIT に対応している EGL Surface コンフィギュレー

ションを eglGetConfigs ()から取得可能

端末名 端末ID GPU EGL_SWAP_BEHAVIOR_PRESERVED_BIT

GALAXY S SC-02B Power VR SGX 540 200MHzAQUOS PHONE SH06-D Power VR SGX 540 384MHzARROWS μ F-07D Adreno 205Xperia SO-02E Adreno 320GALAXY S II WiMAX ISW11SC Mali-400 MPGALAXY S II LTE SC-03D Adreno 220ARROWS Z ISW13F NVIDIA Tegra 3

可能

不可能

Android の場合  (EGL1.4 以上 )

Page 102: モバイル GPU でのハイエンド レンダリングエンジン開発事例

• PowerVR SGX 540 は「不可能」でも EGL_SWAP_BEHAVIOR の値が変更できる– EGL の仕様の例外

EGL_SWAP_BEHAVIOR_PRESERVED_BIT に対応している EGL Surface コンフィギュレー

ションを eglGetConfigs ()から取得可能

端末名 端末ID GPU EGL_SWAP_BEHAVIOR_PRESERVED_BIT

GALAXY S SC-02B Power VR SGX 540 200MHzAQUOS PHONE SH06-D Power VR SGX 540 384MHzARROWS μ F-07D Adreno 205Xperia SO-02E Adreno 320GALAXY S II WiMAX ISW11SC Mali-400 MPGALAXY S II LTE SC-03D Adreno 220ARROWS Z ISW13F NVIDIA Tegra 3

可能

不可能

Android の場合  (EGL1.4 以上 )

Page 103: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Android のパフォーマンス結果

35

38

41

44

Galaxy S (Power VR SGX 540)

EGL_BUFFER_PRESERVEDEGL_BUFFER_DESTROYED

• 効果が見られず

fps

fps

Page 104: モバイル GPU でのハイエンド レンダリングエンジン開発事例

フレームバッファ

• 概要– フロントバッファのスワップの最適化– レンダターゲットの最適化

Page 105: モバイル GPU でのハイエンド レンダリングエンジン開発事例

レンダターゲットの最適化

• 遅い GPU のため– フロントバッファの形式

• RGBA8888 → RGB565

• 解像度を下げる– バックバッファ– フロントバッファ

• 可能な場合のみ。変更出来ない端末もある

Page 106: モバイル GPU でのハイエンド レンダリングエンジン開発事例

レンダターゲットの最適化

• 遅い GPU のため– フロントバッファの形式

• RGBA8888 → RGB565

– 解像度を下げる• バックバッファ• フロントバッファ

– 可能な場合のみ。変更出来ない端末もある

Page 107: モバイル GPU でのハイエンド レンダリングエンジン開発事例

フロントバッファ解像度変更条件

Android の場合

• 変更可能– ただし全てではない– OS のバージョンに依存

• ANativeWindow_setBuffersGeometory()または eglCreateWindowSurface() を利用

Page 108: モバイル GPU でのハイエンド レンダリングエンジン開発事例

フロントバッファ解像度変更条件

iOS の場合

• 変更可能– ただし全てではない– “Retina ディスプレイ”に限られる– 解像度指定はできず Scaling のみ可能

• UIView::contentScaleFactor を利用

Page 109: モバイル GPU でのハイエンド レンダリングエンジン開発事例

バックバッファ解像度

• GPU によって –初期化時にパフォーマンスを計測– 事前に計測した値を使用

• テーブルに保持してある

• 結果を利用してディスプレイ解像度に対してのバックバッファのスケール係数を決定する

Page 110: モバイル GPU でのハイエンド レンダリングエンジン開発事例

最適化手法

Page 111: モバイル GPU でのハイエンド レンダリングエンジン開発事例

検証した GPU• Adreno

– 205, 220, 225, 320• Mali

– 400 MP• PowerVR (SGX)

– 535, 540, 543, 554• Tegra

– Tegra 3

Page 112: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 最適化手法– タイルベース GPU 最適化–オブジェクト描画順– テクスチャフェッチ最適化

Page 113: モバイル GPU でのハイエンド レンダリングエンジン開発事例

タイルベース GPU• タイルベースレンダリングを採用した

GPU– PowerVR, Adreno, Mali

• タイルベースレンダリング (TBR)– フレームバッファへのアクセス

• レンダリング中はフレームバッファにアクセスせず GPU 内のタイルバッファにアクセスする

• 各タイルのレンダリング– 開始時 ⇒ GPU のタイルバッファにロード– 終了時 ⇒ GPU のタイルバッファからストア

Page 114: モバイル GPU でのハイエンド レンダリングエンジン開発事例

タイルのロード , ストア

• 通常のレンダリングでは描画開始時のロードは不必要– 一般的にはレンダリング開始直後にすべてク

リア• OpenGL ES + TBR ではデフォルトではロードが

発生• ストア

– レンダリング後のフレームバッファの内容を使用しない場合

• 例) カラーは必要 , デプス , ステンシルは不必要

• ロード , ストアを制御する GL_EXT がある

Page 115: モバイル GPU でのハイエンド レンダリングエンジン開発事例

GL_EXT_discard_framebuffer• 対応 GPU:Mali, PowerVR

– 古いバージョンの Android OS ではサポートされない

• glDiscardFramebufferEXT()–破棄するカラー , デプス , ステンシルを指定

• 破棄された場合 dirty になる

Page 116: モバイル GPU でのハイエンド レンダリングエンジン開発事例

GL_QCOM_tiled_rendering• 対応 GPU: Adreno• StartTilingQCOM()EndTilingQCOM()– 状態を保持するカラー , デプス , ステンシル

を指定• 保持しないものは dirty になる

– StartTilingQCOM(), EndTilingQCOM()は対にして使用する必要がある

Page 117: モバイル GPU でのハイエンド レンダリングエンジン開発事例

最適化方法

• ロードの必要がない場合– PowerVR, Mali

• レンダリング開始時に glClear を使用してクリア– Adreno

• レンダリング開始時に dirty にする– StartTilingQCOM()

• dirty の場合はロードされない

• ストアの必要がない場合– レンダリングの最後にタイルバッファを dirty にす

る• glDiscardFramebufferEXT()EndTilingQCOM()

• dirty の場合はストアされない

Page 118: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 最適化手法– タイルベース GPU 最適化–オブジェクト描画順– テクスチャフェッチ最適化

Page 119: モバイル GPU でのハイエンド レンダリングエンジン開発事例

オブジェクト描画順

• ここでのオブジェクトの単位は描画順のソートを行う単位– レンダリングエンジンの実装に依存–本セッションではドローコール単位でソート

Page 120: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明オブジェクトパンチスルーオブジェク

トearly-z を考慮し , 手前から順に描画

一般的なケース

半透明オブジェクト奥から順に描画

Page 121: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明オブジェクト

• early-z cull 調査– オーバードローテスト

• Z テスト : near • 1ポリゴン 30 fps になる負荷のフラグメントシェーダを使

用• 手前から描画した場合と、奥から描画した場合で比較

Page 122: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明オブジェクト

05

101520253035

Adreno Mali PowerVR Tegra

fps 1ポリゴン 6手前から ポリゴン 6奥から ポリゴン

• early-z cull 調査– オーバードローテスト

• Z テスト : near • 1ポリゴン 30 fps になる負荷のフラグメントシェーダを使

用• 手前から描画した場合と、奥から描画した場合で比較

Page 123: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明オブジェクト描画順

• Adreno, Mali, Tegra– 手前から順に描画

• オーバードローが発生する可能性がある– オブジェクトが重なっている– オブジェクト内のポリゴンがソートされていない– ポリゴンが交差している

• PowerVR–描画順は考慮しなくてよい

• オーバードローは発生しない– ただし例外あり

» タイル内のポリゴン数が一定を超えるとオーバードローが発生する等

Page 124: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明オブジェクト描画順

• Adreno, Mali, Tegra– 手前から順に描画

• オーバードローは発生する– オブジェクト同士が重なっている– オブジェクト内のポリゴンの並びが手前から順になっ

ていない– ポリゴンが交差している

• PowerVR–描画順は考慮しなくてよい

• 基本的にオーバードローは発生しない– タイル内のポリゴン数が一定を超えるとオーバードローが発生するなど、例外あり

Page 125: モバイル GPU でのハイエンド レンダリングエンジン開発事例

パンチスルーオブジェクト• early-z cull 調査

– オーバードローテスト• 不透明オブジェクトのテストと同じ条件• 不透明オブジェクトテスト時のシェーダに discard命令を追加

– 破棄されるピクセルは無し

Page 126: モバイル GPU でのハイエンド レンダリングエンジン開発事例

パンチスルーオブジェクト

05

101520253035

Adreno Mali PowerVR Tegra

fps 1ポリゴン 6手前から ポリゴン 6奥から ポリゴン

• early-z cull 調査– オーバードローテスト

• 不透明オブジェクトのテストと同じ条件• 不透明オブジェクトテスト時のシェーダに discard命令を追加

– 破棄されるピクセルは無し

Page 127: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明&パンチスルー• early-z cull 調査

– オーバードローテスト• 不透明オブジェクト , パンチスルーオブジェクトを交互に6ポリゴ

ン描画• パンチスルーオブジェクトから描画した場合と、不透明オブジェク

トから描画した場合を比較

Page 128: モバイル GPU でのハイエンド レンダリングエンジン開発事例

不透明&パンチスルー

05

101520253035

Adreno Mali PowerVR Tegra

fps 奥から順 (手前から順 不透明から) (手前から順 パンチスルーから)

• early-z cull 調査– オーバードローテスト

• 不透明オブジェクト , パンチスルーオブジェクトを交互に6ポリゴン描画

• パンチスルーオブジェクトから描画した場合と、不透明オブジェクトから描画した場合を比較

Page 129: モバイル GPU でのハイエンド レンダリングエンジン開発事例

パンチスルーオブジェクト描画順• Mali

– 不透明オブジェクトの後に描画• 描画順は考慮しない

• Adreno, Tegra– 不透明オブジェクトより先に描画

• 不透明はパンチスルーに陰面消去された場合オーバードローが発生しないため

• 常にオーバードローが発生する– 描画順を考慮する必要はない

Page 130: モバイル GPU でのハイエンド レンダリングエンジン開発事例

パンチスルーオブジェクト描画順• PowerVR

– 不透明とパンチスルーオブジェクトを分けて描画

• 不透明オブジェクトのみの場合はオーバードローが発生しないため

• 不透明オブジェクトの前後どちらで描画するのかは不透明オブジェクトとのオーバードロー次第

• 手前から描画

Page 131: モバイル GPU でのハイエンド レンダリングエンジン開発事例

Adreno, Tegra

オブジェクト描画順まとめ

Maliパンチスルー手前から順に描画

PowerVR

半透明奥から順に描画

不透明描画順は考慮しない

パンチスルー手前から順に描画

パンチスルー描画順は考慮しない

半透明奥から順に描画

不透明手前から順に描画

パンチスルー描画順は考慮しない

半透明奥から順に描画

不透明手前から順に描画

Page 132: モバイル GPU でのハイエンド レンダリングエンジン開発事例

コンテンツ

• 最適化手法– タイルベース GPU 最適化–オブジェクト描画順– テクスチャフェッチ最適化

Page 133: モバイル GPU でのハイエンド レンダリングエンジン開発事例

PowerVR テクスチャプリフェッチ• プリフェッチ条件

– UV を varying から値を変えずに使用

– varying のスィズルを x から順に使用

• PowerVR 以外でこのフェッチの有効性をポストプロセスで調査– ¼ ダウンサンプリング– ガウスフィルタ

uniform sampler2D s0;varying vec2 uv0;varying vec4 uv1;

texture2D(s0, uv0); // ○

vec2 uv2 = uv0;uv2 += vec2(0.1, 0.2);texture2D(s0, uv2); // ×

texture2D(s0, uv1.xy); // ○

texture2D(s0, uv1.zw); // ×

Page 134: モバイル GPU でのハイエンド レンダリングエンジン開発事例

PowerVR テクスチャプリフェッチ• プリフェッチ条件

– UV を varying から値を変えずに使用

– varying のスィズルを x から順に使用

• PowerVR 以外でこのフェッチの有効性をポストプロセスで調査– ¼ ダウンサンプリング– ガウスフィルタ

uniform sampler2D s0;varying vec2 uv0;varying vec4 uv1;

texture2D(s0, uv0); // ○

vec2 uv2 = uv0;uv2 += vec2(0.1, 0.2);texture2D(s0, uv2); // ×

texture2D(s0, uv1.xy); // ○

texture2D(s0, uv1.zw); // ×

Page 135: モバイル GPU でのハイエンド レンダリングエンジン開発事例

PowerVR テクスチャプリフェッチ• プリフェッチ条件

– UV を varying から値を変えずに使用

– varying のスィズルを x から順に使用

• PowerVR 以外でこのフェッチの有効性をポストプロセスで調査– ¼ ダウンサンプリング– ガウスフィルタ

uniform sampler2D s0;varying vec2 uv0;varying vec4 uv1;

texture2D(s0, uv0); // ○

vec2 uv2 = uv0;uv2 += vec2(0.1, 0.2);texture2D(s0, uv2); // ×

texture2D(s0, uv1.xy); // ○

texture2D(s0, uv1.zw); // ×

Page 136: モバイル GPU でのハイエンド レンダリングエンジン開発事例

PowerVR テクスチャプリフェッチ• プリフェッチ条件

– UV を varying から値を変えずに使用

– varying のスィズルを x から順に使用

• PowerVR 以外でこのフェッチの性能をポストプロセスで調査– ¼ ダウンサンプリング– ガウスフィルタ

uniform sampler2D s0;varying vec2 uv0;varying vec4 uv1;

texture2D(s0, uv0); // ○

vec2 uv2 = uv0;uv2 += vec2(0.1, 0.2);texture2D(s0, uv2); // ×

texture2D(s0, uv1.xy); // ○

texture2D(s0, uv1.zw); // ×

Page 137: モバイル GPU でのハイエンド レンダリングエンジン開発事例

テクスチャフェッチ比較対象

• バーテックスシェーダ UV生成– varying の値を変えずに使

用– varying 数をできるだけ削減

uniform sampler2D s0;varying vec4 uv0;varying vec4 uv1;

texture2D(s0, uv0.xy);texture2D(s0, uv0.zw);texture2D(s0, uv1.xy);texture2D(s0, uv1.zw);

uniform sampler2D s0;varying vec2 uv;uniform vec2 ofs0;uniform vec2 ofs1;Uniform vec2 ofs2;

texture2D(s0, uv+ofs0);texture2D(s0, uv+ofs1);texture2D(s0, uv+ofs2);

• フラグメントシェーダ UV生成– varying は1つ

Page 138: モバイル GPU でのハイエンド レンダリングエンジン開発事例

テクスチャフェッチ検証環境

• カラーフォーマット: ARGB8888• Precision

– バーテックスシェーダ: highp– フラグメントシェーダ: mediump

• パフォーマンス計測方法– フレームレートから計測– 60fps 以下にするため解像度を調整

Page 139: モバイル GPU でのハイエンド レンダリングエンジン開発事例

1/4 ダウンサンプリング• テクスチャフェッチ4回

Page 140: モバイル GPU でのハイエンド レンダリングエンジン開発事例

1/4 ダウンサンプリング結果

0

0.2

0.4

0.6

0.8

1

1.2

205 220 225 320 400 MP T604 540

PowerVRプリフェッチ UVバーテックス 生成 UVフラグメント 生成↑Fast

PowerVR

MaliAdreno Tegra 3

Page 141: モバイル GPU でのハイエンド レンダリングエンジン開発事例

ガウスフィルタ• テクスチャフェッチ7回

Page 142: モバイル GPU でのハイエンド レンダリングエンジン開発事例

ガウスフィルタ結果

0

0.2

0.4

0.6

0.8

1

1.2

205 220 225 320 400 MP T604 540

PowerVRプリフェッチ UVバーテックス 生成 UVフラグメント 生成

PowerVR

MaliAdreno Tegra 3

↑Fast

Page 143: モバイル GPU でのハイエンド レンダリングエンジン開発事例

テクスチャフェッチ結果

• Mali-400 MP– PowerVR プリフェッチが有効

• UV精度も向上する

• Adreno 200 シリーズ , Tegra 3– PowerVR プリフェッチの有効性は見られない– varying 数増加によるパフォーマンス低下は確認で

きず• フラグメントシェーダ負荷の少ないバーテックス UV生成推奨

– PowerVR のプリフェッチを使用して問題ない

• Adreno 320, Mali-T604– varying 数削減が効果的

Page 144: モバイル GPU でのハイエンド レンダリングエンジン開発事例

まとめ

• 性能差が大幅に異なる GPU に対応が必要• OS, GPU, 端末の違いによるさまざまな

問題が発生– 特に Android では仕様書などのドキュメン

トが信用できないことが多い• 各 GPU の最適化手法の調査 , 検証が必要

Page 145: モバイル GPU でのハイエンド レンダリングエンジン開発事例

謝辞

• (株)トライエース研究開発部–五反田 義治

Page 146: モバイル GPU でのハイエンド レンダリングエンジン開発事例

ご質問は?

http://research.tri-ace.com