着色器数据类型和精度
在unity中,标准的shader语言是HLSL,一般的HLSL数据类型都是支持的。然而,Unity有一些额外的HLSL类型,对移动平台有更好的支持。
基础数据类型
在shader中,主要的计算数据类型是 浮点数据(在普通的变成语言中,比如C#中等于float)。几种浮点类型的变种是: float、half 和 fixed(和 它们的向量/矩阵一样,变种为 half3,float4x4)。这些类型精度不同(而且,因此,性能或者功效使用):
高精度:float
最高精度的浮点数值;一般来说是32位值。
全浮点数值精度类型一般用来表达世界空间位置,贴图坐标或者涉及复杂运算的函数标量,比如三角函数、幂运算。
中精度:half
中等精度浮点数值;一般为16位值。
半精度类型一般用来表示短向量、方向、物体空间坐标,高动态范围颜色。
低精度:fixed
最低精度固定点数值。一般为11位值,范围为-2.0~+2.0和 1/256精度。
固定精度用来表示普通颜色和对颜色简单的操作。
整型数据类型
整型数据经常用来表示循环计数或者数组指数。为此,他们通常在不同平台上都能够很好的工作。
根据平台不同,整型数据可能不被GPU所兼容。比如,D3D9和 OpenGL ES2.0 GPU只能够操作浮点数据,而简单整数表达式(涉及位或逻辑运算)则可能使用相当复杂的浮点数学指令来模拟。
D3D 11,OpenGL ES 3,Metal和其它现代平台则对整型数据类型拥有较好的支持,所以使用位移位和位掩蔽可以如预期一样工作。
复合 向量/矩阵类型
HLSL有内置的由基础数据类型衍生而来的向量和矩阵类型。比如,float3是一个拥有x、y、z分量的三维向量,half4则是中等精度的拥有x、y、z、w分量的4维向量。当然,向量也可以被用来表达 颜色的r、g、b、a分量。
矩阵类型和向量类型差不多。比如,一个float4x4就是 4x4 维度的矩阵。注意一些平台只支持正方形矩阵,特别是OpenGL ES 2.0.
贴图/采样器类型
典型的你在HLSL代码中声明贴图变量和下面类似:
sampler2D _MainTex; samplerCUBE _Cubemap;
对于移动平台,这些将翻译成“低精度采样器”,比如,纹理被期望具有低精度的数据。如果你知道你的贴图包含了HDR颜色,那么你需要用半精度采样器:
sampler2D_half _MainTex; samplerCUBE_half _Cubemap;
如果你的贴图包含全浮点精度数据(比如 深度贴图),使用全精度采样器:
sampler2D_float _MainTex; samplerCUBE_float _Cubemap;
精度、硬件支持和表现
在PC 的GPU上使用 float/half/fixed数据类型时,会出现一个问题,那就是全部都会变成高精度。也就是说,对于所有的 PC GPU,你在shader中使用啥子数据类型根本没什么影响。他们在计算时,总是使用32位的全精度浮点数。
只有当针对移动gpu的时候,一半和固定的类型才会变得有意义,这些数据类型主要是从耗电量来考虑。记住你需要在移动平台上测试你的shader,来看看有没有精度问题。
即便在移动GPU上,不同的GPU家族对精度支持也不同。下面是一些数据:
GPU Family | 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 vertex 24 fragment | ||
ARM Mali T6xx/7xx | 32 | 16 | |
ARM Mali 400/450 | 32 vertex 16 fragment | ||
NVIDIA X1 | 32 | 16 | |
NVIDIA K1 | 32 | ||
NVIDIA Tegra 3/4 | 32 | 16 |
大部分现代移动GPU实际上只支持 32位(float)或者16位(half/fixed)类型。一些老的GPU则对顶点shader和片段shader计算指令有不同的精度。
使用较低的精度通常会更快,这可能是由于GPU寄存器分配的改进,或者是由于特殊的“快速路径”执行单元,用于某些较低精度的数学运算。即使没有原始的性能优势,使用更低的精度也会减少GPU上的电量,从而提高电池的使用寿命。
一般的经验法则是,除了位置和纹理坐标之外,所有的东西都要有half精度。如果half精度不足以计算,才提高精度。
对无穷大、不是数值或者其他特殊浮点值的支持
对于特殊浮点值的支持,这要根据你的GPU来分别讨论。
所有支持 D3D 10的 PC GPU都能很好地支持IEEE 754浮点数据标准。这也就意味着浮点数在GPU上表现和在编程语言在CPU中表现一样的好。
移动GPU则有一些轻微的不同等级的支持。在一些平台上, 0除以0结果不是一个数值;在其它平台则可能结果为无穷大,0或者任何其它随机的值。一定要在你的目标平台上测试你的shader来确保他们是被支持的。
外部的GPU文档
GPU供应商对于他们的GPU提供了一个全方位的说明文档,包括GPU的表现和能力,详细情况请看下面:
- ARM Mali Guide for Unity Developers
- Qualcomm Adreno OpenGL ES Developer Guide
- PowerVR Architecture Guides