だらけ者だらけ

だらけ者だらけの遊び場

パーティクルにLight追加したらGPU負荷が跳ね上がった話

発端: パーティクル置いたら"Tiled" Deferredが走るようになった。


何もないシーン。 f:id:tempkinder:20141226170124j:plain

プロファイルしてみる。ライティングは1.0msぐらい。

(Startar Contetnsの)P_Sparksをおいてみた。

プロファイルしてみる。ライティングは4.03ms!!!!

TiledDeferredという処理が走るようになっている。

どうして? パーティクルにライトモジュールがあるからです。

ということが起きました。実は、パーティクルのライトが一個でもあると、裏でこの"Tiled Deferred"が走ります。

この処理、非常に大雑把に言うと、ライトが影響を与える画像の範囲を前もって調べ、不要なピクセルへの描画処理を省く手法です。 ライトがシーンに沢山ある場合は非常に高速になるのですが。。。ライトが高々数個の場合は逆で、この”前もって調べる”という部分のコストが一定量かかってしまい、それらが処理負荷を増大させてしまいます。 仕組みについて詳しく説明しません。案の定いつもどおり要するに率直におおかたの予想通り平たくところはばからずに正直に言ってしまえば、もんしょさんがこちらについて詳しく書いておりますので、そちらを参考にしてください。

DirectXの話 第125回 - もんしょの巣穴

余談ですが、UE4の基本設定では、普通のポイントライトを80個以上置くとTiledDeferredが走ります。(もんしょさん、ありがとうございます。) 逆を言うと、それぐらいライトの数が増えないとTiledDeferredによる高速化の恩恵を得られないということです。なのに、パーティクルのライトは一個でもあると、このタイル化処理が走ってしまうのです。

では、パーティクルライトを使う&Tiled Deferredを走らせない という方法は取れないか?少し調べてました。.iniの設定等ではできなそうです。

ありました!.iniファイルに

r.TiledDeferredShading=0

と記載するか、下図の様に、Blueprintで直接コンソールコマンドを打ち込むことで、普通のディファードレンダリングにすることができます。(一括での変更のみ。このパーティクルライトだけTiledで。。。とかはできません。)

パーティクルライトは非常に綺麗なので使いたい人は多いと思います。 このパーティクルのライティングについてはtoaru_designerさんの以下のスライドが非常にわかりやすく説明していますので、こちらを参考にしてください! ただし、パーティクルライトの数が少ない場合は、上記のコマンドでTiledDeferredを走らせない方が良いでしょう。

まとめ

問題
パーティクルのライトモジュールを置くとTiledDeferredというものが走ってGPUコストが上がる。ライトが沢山ある場合は高速な機能だが、ライトが少ない場合は逆に負荷を高めてしまうのでOffにしたほうが良い。

TiledDeferredをOffにする方法
・”r.TiledDeferredShading=0”をDefaultEngine.iniに追加
・もしくはexecute console commandで”r.TiledDeferredShading 0”と打ち込む
備考
これはSM5が動くPC版等での設定です。試していませんが、モバイル版ではこのTiledDeferredの処理は走りません。試してませんが。試してませんけど。誰か試して。

原因: なんでTiledDeferredが走るの?

本件の問題となるコードも載せておきます。(UE4.6で検証) FDeferredShadingSceneRenderer::RenderLights()(RenderLights.cpp)内の以下コードです。

if (NumSortedLightsTiledDeferred > 0 || SimpleLights.InstanceData.Num() > 0) 
{
    // Update the range that needs to be processed by standard deferred to exclude the lights done with tiled
    StandardDeferredStart = NumSortedLightsTiledDeferred;
    RenderTiledDeferredLighting(RHICmdList, SortedLights, NumSortedLightsTiledDeferred, SimpleLights);
}               }

SimpleLightsが一個でもシーンにあると自動的にTiledDeferredが走ります。 このSimpleLightsがどういう過程で生成されるのか詳しく見ていませんが、パーティクルのLightモジュールは、SimpleLightsとして生成されるようです。

この部分を読むとモバイルなどではタイルベースの処理は走らないようになっている様ですが、試してはおりません。

読んでいただきありがとうございます。

f:id:tempkinder:20140112115953j:plain

なんか見つけたらちょいちょい書いてきます。