The standard Shader language in Unity is HLSL, and general HLSL data types are supported. However, Unity has some additions to the HLSL types, particularly for better support on mobile platforms.
La mayoría de los cálculos en shaders se llevan a cabo en números de punto flotante (que sería float
en lenguajes de programación regulares como C#). Existen varias variantes de tipos de punto flotante: float
,half
y fixed
(así como las variantes de vector/matriz de ellas, comohalf3
y float4x4
). Estos tipos difieren en precisión (y, en consecuencia, en rendimiento o consumo de energía):
float
Valor de punto flotante de precisión más alta; Generalmente 32 bits (como float
desde lenguajes de programación regulares).
La precisión completa del float
se utiliza generalmente para las posiciones del espacio del mundo,
coordenadas de textura, o cálculos escalares involucrando funciones complejos como trigonometría o Potencia/exponenciación.
half
Valor de punto flotante de precisión media; Generalmente 16 bits (rango de –60000 a +60000, con unos 3 dígitos decimales de precisión).
La media precisión es útil para vectores cortos, direcciones, posiciones de espacio de objeto, colores de alto rango dinámico.
fixed
Valor de punto fijo de precisión más baja. Generalmente 11 bits, con un rango de –2.0 a +2.0 y precisión 1 / 256th.
La precisión fija es útil para los colores regulares (normalmente almacenados en texturas regulares) y para realizar operaciones sencillas sobre ellos.
Los enteros (tipo de datos int
) se utilizan a menudo como contadores de bucle o índices de matriz. Para este propósito, generalmente funcionan bien en varias plataformas.
Dependiendo de la plataforma, los tipos enteros podrían no ser compatibles con la GPU. Por ejemplo, las GPU Direct3D 9 y OpenGL ES 2.0 sólo funcionan con datos de punto flotante, y las expresiones enteras de apariencia simple (que implican bits o operaciones lógicas) pueden emularse utilizando instrucciones matemáticas de punto flotante bastante complicadas.
Direct3D 11, OpenGL ES 3, Metal y otras plataformas modernas tienen soporte adecuado para tipos de datos enteros, por lo que el uso de los desplazamientos de bit y el bit masking funciona como se esperaba.
HLSL incorpora tipos vectoriales y matriciales que se crean a partir de los tipos básicos. Por ejemplo, float3
es un vector 3D con componentes .x, .y, .z, yhalf4
es un vector 4D de precisión media con componentes .x, .y, .z, .w. Alternativamente, los vectores pueden indexarse utilizando los componentes .r, .g, .b, .a, que es útil cuando se trabaja en colores.
Los tipos de matriz se construyen de manera similar; Por ejemplo float4x4
es una matriz de transformación 4x4. Tenga en cuenta que algunas plataformas sólo admiten matrices cuadradas, especialmente OpenGL ES 2.0.
Typically you declare textures in your HLSL code as follows:
sampler2D _MainTex;
samplerCUBE _Cubemap;
For mobile platforms, these translate into “low precision samplers”, i.e. the textures are expected to have low precision data in them. If you know your texture contains HDR colors, you might want to use half precision sampler:
sampler2D_half _MainTex;
samplerCUBE_half _Cubemap;
Or if your texture contains full float precision data (e.g. depth texture), use a full precision sampler:
sampler2D_float _MainTex;
samplerCUBE_float _Cubemap;
Una complicación del uso de tipo de datos float
/half
/fixed
es que las GPUs de PC son siempre de alta precisión. Es decir, para todas las
PC (Windows/Mac/Linux) GPUs, no importa
si usted escribe tipos de datos float
, half
or fixed
en sus shaders.
Siempre calculan todo en una precisión punto flotante
completo de 32-bit.
Los tipos half
y fixed
solo se vuelven relevantes cuando
se apunta a GPUs móviles, donde estos tipos principalmente existen para
restricciones de poder (y a veces rendimiento). Tenga en
cuenta que usted necesitará probar sus shaders en móvil para ver
Si o no se está ejecutando en problemas de precisión/ numéricos.
Incluso en GPUs móviles, el soporte de precisión diferente varia entre familias GPU. A continuación se ofrece una descripción general de cómo la familia GPU trata cada tipo de punto flotante (indicado por el número de bits utilizados para este):
Familia 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 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 |
La mayoría de las GPU móviles actuales sólo soportan
ya sea números de 32 bits (utilizados para el tipo float
) o números de 16 bits
(Utilizado tanto para los tipos half
comofixed
). Algunas GPU más antiguas tienen diferentes precisiones para los cálculos de vertex shader y de fragment shader.
El uso de una precisión más baja a menudo puede ser más rápido, ya sea debido a la mejora de la asignación de registro GPU, o debido a una ejecución especial “ruta rápido” de unidades para ciertas operaciones matemáticas de menor precisión. Incluso cuando no hay ventaja de rendimiento en bruto, el uso de menor precisión a menudo utiliza menos energía en la GPU, lo que lleva a una mejor duración de la batería.
Una regla general es comenzar con la mitad de precisión para todo, excepto las posiciones y las coordenadas de textura. Sólo aumentar la precisión si la media precisión no es suficiente para algunas partes del cálculo.
El soporte para valores de punto flotante especiales puede ser diferente dependiendo de la familia de GPU (principalmente móvil) que esté ejecutando.
Todas las GPUs de PC que soportan Direct3D 10 soportan un estándar punto flotante IEEE 754 muy bien especificado. Esto significa que los número float se comportan exactamente como lo hacen regularmente en lenguajes de programación en la CPU.
Las GPUs móviles tienen niveles diferentes de soporte. En algunos, dividir cero por cero podría resultar en un NaN (“no un número”); en otros podría dar como resultado infinito, cero u otro valor sin especificar. Asegúrese de probar sus shader en el dispositivo objetivo para revisar si son soportados.
Los proveedores de GPU tienen guías detalladas sobre rendimiento y capacidades de sus GPUs. Mire estos por detalles: