Version: 2022.1
言語: 日本語
ビルトインのシェーダー変数
サンプラー状態の利用

シェーダーのデータ型と精度

The standard Shader language in Unity is HLSL, and general HLSL data types are supported. However, Unity handles some data types differently from HLSL, particularly to provide better support on mobile platforms.

基本的なデータ型

Shaders carry out the majority of calculations using floating point numbers (which are float in regular programming languages like C#). In Unity’s implementation of HLSL, the scalar floating point data types are float, half, and fixed. These data types differ in precision and, consequently, performance or power usage. There are also several related data types for vectors and matrices such as half3 and float4x4.

高精度: float

This is the highest precision floating point data type. On most platforms, float values are 32 bits like in regular programming languages.

Full float precision is generally useful for world space positions, texture coordinates, or scalar calculations that involve complex functions such as trigonometry or power/exponentiation. If you use lower precision floating point data types for these purposes, it can cause precision-related artifacts. For example with texture coordinates, a half doesn’t have enough precision to accurately represent 1-texel offsets of larger textures.

中精度: half

This is a medium precision floating point data type. On platforms that support half values, they are generally 16 bits. On other platforms, this becomes float.

half values have a smaller range and precision than float values.

Half precision is useful to get better shader performance for values that don’t require high precision such as short vectors, directions, object space positions, and high dynamic range colors.

低精度: fixed

This is only supported by the OpenGL ES 2.0 Graphics API. On other APIs it becomes the lowest supported precision (half or float).

This is the lowest precision fixed point value and is generally 11 bits. fixed values range from –2.0 to +2.0 and have a precision of 1/256.

fixed 精度は、標準カラー (一般的に標準テクスチャに保管されるので) とそれらの単純な制御に使用されます。

Floating point numbers

Unity’s shader compiler ignores floating point number suffixes from HLSL. Floating point numbers with a suffix therefore all become float.

This code shows a possible negative impact of numbers with the h suffix in Unity: half3 packedNormal = ...; half3 normal = packedNormal * 2.0h - 1.0h;

Since the h suffix is ignored, the shader compiler generates code that executes these steps: 1. Calculate an intermediary normal value in high precision (float3) 2. Convert the intermediary value to half3. This reduces your shader’s performance.

This code is more efficient because it only uses half values in its calculations: half3 packedNormal = ...; half3 normal = packedNormal * half(2.0) - half(1.0);

整数データ型

整数 (int データ型) はしばしばループカウンターや配列のインデックスとして使用されます。そのため、通常は、さまざまなプラットフォームで問題なく使用できます。

プラットフォームによっては、整数型がGPU にサポートされていないことがあります。例えば、Direct3D 9 と OpenGL ES 2.0 GPU は、浮動小数点データ上でのみ作動します。そのため、シンプルに見える整数表現 (ビットやロジカルオペレーションに関する) は、ある程度複雑な浮動小数点の数式を使用してエミュレーションされていることがあります。

Direct3D 11、OpenGL ES 3、Metal やその他の現段階で使用されている多くのプラットフォームでは、整数のデータ型は適切にサポートされています。そのため、ビットシフトやビットマスクを使用しても、想定通り作動します。

合成のベクトル/行列の型

HLSL には、基本の型から作成されたビルトインのベクトル型と行列型があります。例えば、float3 は .x、.y、.z コンポーネントを含む 3D ベクトルです。また、half4 は、中精度の 4D ベクトル (.x、.y、.z、.w コンポーネントを含む) です。あるいは、カラーを使用するときに有用な .r、.g、.b、.a コンポーネントを使用して、ベクトルをインデックス化することができます。

行列型も同様に作成されます。例えば、float4x4 は 4x4 変換行列です。プラットフォームによっては、OpenGL ES 2.0 でよく知られているように正方行列だけしかサポートしないものもあるので注意してください。

テクスチャ/サンプラーの型

多くの場合、HLSL コードではテクスチャを以下のように宣言します。

sampler2D _MainTex;
samplerCUBE _Cubemap;

モバイルプラットフォームでは、これらは “低精度サンプラー” に変換されます。つまり、テクスチャには低精度のデータが含まれることが期待されます。 Unity プロジェクト全体のデフォルトのサンプラー精度は、Player Settings の Shader precision model ドロップダウンで変更することができます。 テクスチャに HDR カラーが含まれることが分かっている場合は、半精度サンプラーを使用するとよいでしょう。

sampler2D_half _MainTex;
samplerCUBE_half _Cubemap;

または、テクスチャがフルの float 精度のデータを含む場合 (例えば 深度テクスチャ)、最高精度を使用します。

sampler2D_float _MainTex;
samplerCUBE_float _Cubemap;

精度、ハードウェアのサポートとパフォーマンス

float/half/fixed データ型を使用する上での厄介な問題の 1 つは、PC の GPU は 常に 高精度であるということです。つまり、すべての PC の (Windows/Mac/Linux) GPU にとって、シェーダーで floathalffixed の中のどのデータ型を使用するかは重要ではありません。PC の GPU は常にフルの 32 ビット浮動小数点精度ですべてを計算します。

halffixed型は、モバイルの GPU をターゲットとする場合にのみ意味があります。これらのタイプは主に電力 (および、場合によってはパフォーマンス) の制約のために存在します。そのため、精度/数値の問題があるかどうか確認するためには、モバイルでシェーダをテストする必要があります。

モバイルの GPU であっても、GPU ファミリーによって精度のサポートにさまざまな違いがあります。以下は、各モバイル GPU ファミリーが各浮動小数点型を処理する方法の概要です (消費されるビット数で表示)。

GPU グループ float half fixed
PowerVR Series 6/7 32 16
PowerVR SGX 5xx 32 16 11
Qualcomm Adreno 4xx/3xx 32 16
Qualcomm Adreno 2xx 32 (頂点)、24 (フラグメント)
ARM Mali T6xx/7xx 32 16
ARM Mali 400/450 32 (頂点)、16 (フラグメント)
NVIDIA X1 32 16
NVIDIA K1 32
NVIDIA Tegra 3/4 32 16

最近良く使われるモバイルのほとんどの GPU は、実際には 32 ビット数 (float 型に使用) または 16 ビット数 (halffixed 型の両方に使用) のいずれかしかサポートしていません。一部の古い GPU では、頂点シェーダーとフラグメントシェーダーの計算で精度が異なります。

低精度を使用すると高速になることがよくあります。それは、GPU レジスターの割り当てが改善されたため、または特定の低精度数学演算用の特別な “高速パス” 実行ユニットによるためです。直接のパフォーマンス上の利点がない場合でも、低い精度を使用すると GPU の消費電力が少なくなるため、バッテリー寿命が長くなります。

一般的に推奨される使用法は、位置とテクスチャ座標を除くすべてに half (中精度) を使用します。計算で精度にいくらか不十分な個所がある場合にのみ、精度を上げます。

無限、NaN、他の特別な浮動小数点値の適用

計算に使用される精度が異なる GPU グループ (ほとんどモバイル) によって異なるように、特別な浮動小数点値のサポートも異なります。

Direct3D 10 をサポートするすべての PC の GPU は、非常にうまく指定された IEEE 754 浮動小数点規格をサポートします。つまり、浮動小数点数は、CPU 上の通常のプログラミング言語の場合とまったく同じように動作します。

モバイル GPU のサポートレベルは、わずかに異なります。例えば、ゼロをゼロで除算すると NaN (“数字ではない”) になるモバイルがありますが、無限大、ゼロ、または、その他の特定できない値になるものもあります。ターゲットデバイスでシェーダーをテストして、それらのサポートを確認してください。

外部 GPU ドキュメンテーション

GPU には、そのパフォーマンスや能力に関してベンダーによる詳しいガイドがあります。詳細は、それらを参照してください。

関連項目

ビルトインのシェーダー変数
サンプラー状態の利用