【Unity】Shaderで使うfloat,half,fixed精度によるパフォーマンスの違い
シェーダーを書いていて、特にモバイル端末でのパフォーマンスが気になることが多々あります。なんとかフレームレートを改善して快適な操作を保ちたい。そんな中、いくつかの最適化方法を試す中で恐らく試すであろう
「データ型の精度を調整する」
ことに関して検証してみようと思います。正直、実際問題どの程度の改善がみられるのかシンプルなベンチマークを取る機会が少なかったのでUnityを使って改めて計測してみようと思いました。
目次
検証環境
- Unityバージョン 2019.1.0f2
- 端末 HTC 10
Cubeにテクスチャを貼り付けたものを5000体インスタンスを生成する。その際のフラグメントのコードは以下の通り
float4 frag (v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
return col;
}
とにかくシンプルなものにしました。このfloatの部分をhalf、fixedと置き換えて計測します。
精度の違い
- half: 16bit
- fixed: 11bit
- float: 32bit
パフォーマンス計測には以下のAssetを使用しました。
[Graphy] – Ultimate FPS Counter – Stats Monitor & Debugger – Asset Store
計測結果
- float 25~27
- half 30~31
- fixed 29~31
float の結果は予想通りでしたが、シンプル過ぎたシェーダーのせいかhalfとfixedとでは、誤差の範囲での結果となりました。
もう少し計算量を増やしてみる
少し計算量を増やしてみます。
float4 frag (v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
float4 col2 = tex2D(_MainTex, i.uv);
float4 col3 = tex2D(_MainTex, i.uv);
float4 col4 = tex2D(_MainTex, i.uv);
return col * col2 * col3 * col4;
}
- float 20~22
- half 20~22
- fixed 20~22
検証端末ではhalfとfixedの差は見受けられない結果となりました。少し不思議ですが、これはGPUの種類によって、サポートされているデータ型の精度が異なるための様です。
使い分け
どのデータ型を使うべきかは公式にも書いてありますが
高精度:
https://docs.unity3d.com/ja/current/Manual/SL-DataTypesAndPrecision.htmlfloat
float は最高精度の浮動小数点値で、通常のプログラミング言語のfloat
と同じように一般な 32 ビットです。
フルfloat
の精度は、一般に、ワールド空間位置、テクスチャ座標、または三角法やべき乗/べき乗などの複雑な関数を含むスカラー計算に使用されます。
中精度:half
half は中精度の浮動小数点値で、一般に 16 ビットです (–60000 から +60000 の範囲で、小数点以下約 3 桁)。
half は、ショートベクトル、方向、オブジェクト空間位置、HDR カラー に使用されます。
低精度:fixed
fixed は低精度で、固定小数点数です。一般的に 11 ビットで、–2.0 から +2.0 の範囲で、1/256 精度です。
fixed 精度は、標準カラー (一般的に標準テクスチャに保管されるので) とそれらの単純な制御に使用されます。
これで良いと思います。また、PC環境ではどれもfloatとして扱われるそうです。
結論
floatよりhalf・fixedに変更することでフレームレートの改善は見受けられるので試す価値はある。