Compartir a través de


Sintaxis de variables

Utilice las siguientes reglas de sintaxis para declarar variables HLSL.

[Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [: Packoffset] [: Register]; [Annotations] [= Initial_Value]

Parámetros

Storage_Class

Modificadores opcionales de clase de almacenamiento que proporcionan sugerencias del compilador sobre el ámbito y la duración de las variables; los modificadores se pueden especificar en cualquier orden.

Valor Descripción
extern Marca una variable global como entrada externa al sombreador; este es el marcado predeterminado para todas las variables globales. No se puede combinar con static.
nointerpolation No interpola las salidas de un sombreador de vértices antes de pasarlas a un sombreador de píxeles.
precise La palabra clave precise, cuando se aplica a una variable, restringirá los cálculos utilizados para generar el valor asignado a esa variable de las maneras siguientes:
  • Las operaciones independientes se mantienen independientes. Por ejemplo, cuando una operación mul y add podrían haberse fusionado en una operación mad, precise obliga a que las operaciones permanezcan separadas. En su lugar, debe usar explícitamente la función intrínseca mad.
  • Se mantiene el orden de las operaciones. Cuando el orden de las instrucciones puede haberse modificado para mejorar el rendimiento, precise garantiza que el compilador conserve el orden como se escribe.
  • Las operaciones no seguras de IEEE están restringidas. Cuando el compilador podría haber usado operaciones matemáticas rápidas que no tienen en cuenta los valores NaN (no un número) e INF (infinito), precise obliga a que se respeten los requisitos de IEEE relativos a los valores NaN e INF. Sin precise, estas optimizaciones y operaciones matemáticas no son seguras para IEEE.
  • Calificar una variable precise no realiza operaciones que usan la variable precise. Dado que precise se propaga solo a las operaciones que contribuyen a los valores asignados a la variable calificada para precise, hacer que los cálculos deseados sean de tipo precise puede ser complicado, por lo que se recomienda marcar las salidas del sombreador como precise directamente donde se declaran, tanto si se encuentran en un campo de estructura, como en un parámetro de salida o en el tipo de valor devuelto de la función de entrada. La capacidad de controlar las optimizaciones de este modo mantiene la invariabilidad de los resultados para la variable de salida modificada al desactivar las optimizaciones que podrían afectar a los resultados finales debido a las diferencias de precisión acumuladas. Resulta útil cuando se quieren sombreadores para la teselación para mantener costuras de revisión estancas o hacer coincidir los valores de profundidad sobre varios pasos. Código de ejemplo:
    HLSLmatrix g_mWorldViewProjection;
    void main(in float3 InPos : Position, out precise float4 OutPos : SV_Position)
    {
    // operation is precise because it contributes to the precise parameter OutPos
    OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );
    }
shared Marca una variable para compartir entre efectos; se trata de una sugerencia para el compilador.
groupshared Marca una variable para la memoria compartida de grupo de subprocesos para sombreadores de proceso. En D3D10, el tamaño total máximo de todas las variables con la clase de almacenamiento groupshared es de 16 kb, en D3D11, el tamaño máximo es de 32 kb. Consulte ejemplos.
static Marca una variable local para que se inicialice una vez y persista entre las llamadas de función. Si la declaración no incluye un inicializador, el valor se establece en cero. Una variable global marcada como static no es visible para una aplicación.
uniform Marca una variable cuyos datos son constantes durante la ejecución de un sombreador (como un color de material en un sombreador de vértices); las variables globales se consideran uniform de forma predeterminada.
volatile Marca una variable que cambia con frecuencia; se trata de una sugerencia para el compilador. Este modificador de clase de almacenamiento solo se aplica a una variable local.
Nota: actualmente, el compilador HLSL ignora este modificador de clase de almacenamiento.

Type_Modifier

Modificador de tipo variable opcional.

Valor Descripción
const Marca una variable que no se puede cambiar mediante un sombreador, por lo tanto, debe inicializarse en la declaración de variable. Las variables globales se consideran const de forma predeterminada (suprimen este comportamiento proporcionando la marca /Gec al compilador).
row_major Marca una variable que almacena cuatro componentes en una sola fila para que se puedan almacenar en un único registro de constantes.
column_major Marca una variable que almacena 4 componentes en una sola columna para optimizar la matemática de la matriz.

Nota:

Si no especifica un valor de type-modifier, el compilador usa column_major como valor predeterminado.

Tipo

Cualquier tipo HLSL que aparezca en Tipos de datos (DirectX HLSL) .

Name[Index]

Cadena ASCII que identifica de forma única una variable de sombreador. Para definir una matriz opcional, use index para el tamaño de la matriz, que es un entero positivo = 1.

Semántica

Información opcional de parameter-usage, que utiliza el compilador para vincular entradas y salidas del sombreador. Hay varias semánticas predefinidas para sombreadores de vértices y píxeles. El compilador omite la semántica a menos que se declare en una variable global o un parámetro pasado a un sombreador.

Packoffset

Palabra clave opcional para empaquetar manualmente las constantes del sombreador. Consulte packoffset (DirectX HLSL).

Registro

Palabra clave opcional para asignar manualmente una variable de sombreador a un registro determinado. Consulte register (DirectX HLSL).

Annotation(s)

Metadatos opcionales, en forma de cadena, adjuntos a una variable global. Una anotación se utiliza en el marco de efectos y la ignora HLSL; para ver una sintaxis más detallada, consulte sintaxis annotation.

Initial_Value

Valores iniciales opcionales; el número de valores debe coincidir con el número de componentes de Type. Cada variable global marcada como extern debe inicializarse con un valor literal; cada variable marcada como static debe inicializarse con una constante.

Las variables globales que no están marcadas como static o extern no se compilan en el sombreador. El compilador no establece automáticamente valores predeterminados para variables globales y no puede usarlos en optimizaciones. Para inicializar este tipo de variable global, use la reflexión para obtener su valor y, a continuación, copie el valor en un búfer de constantes. Por ejemplo, puede usar el método ID3D11ShaderReflection::GetVariableByName para obtener la variable, usar el método ID3D11ShaderReflectionVariable::GetDesc para obtener la descripción de la variable de sombreador y obtener el valor inicial del miembro DefaultValue de la estructura D3D11_SHADER_VARIABLE_DESC. Para copiar el valor en el búfer de constantes, debe asegurarse de que el búfer se creó con acceso de escritura de CPU (D3D11_CPU_ACCESS_WRITE). Para obtener más información sobre cómo crear un búfer de constantes, consulte Procedimiento: Creación de un búfer de constantes.

También puede usar el marco de efectos para procesar automáticamente la reflexión y establecer el valor inicial. Por ejemplo, puede usar el método ID3DX11EffectPass::Apply.

Importante

La compatibilidad con esta característica se quitó en Direct3D 12, incluida la capacidad de reflejar inicializadores predeterminados.

Ejemplos

Estos son varios ejemplos de declaraciones de variables de sombreador.

float fVar;
float4 color;

int iVar[3];

uniform float4 position : SV_POSITION; 

//Default initializers; supported up to Direct3D 11.

float fVar = 3.1f;
int iVar[3] = {1,2,3};
const float4 lightDirection = {0,0,1};

Compartidas por grupos

HLSL permite a los subprocesos de un sombreador de proceso intercambiar valores a través de la memoria compartida. HLSL proporciona primitivos de barrera como GroupMemoryBarrierWithGroupSync, etc. para garantizar la ordenación correcta de lecturas y escrituras en memoria compartida en el sombreador y para evitar carreras de datos.

Nota:

El hardware ejecuta subprocesos en grupos (distorsiones o frentes de onda) y a veces se puede omitir la sincronización de barreras para aumentar el rendimiento cuando solo es correcto sincronizar subprocesos que pertenecen al mismo grupo. Pero desaconsejamos esta omisión por estas razones:

  • Esta omisión produce código no portátil, que podría no funcionar en algún hardware y no funciona en rasterizadores de software que normalmente ejecutan subprocesos en grupos más pequeños.
  • Las mejoras de rendimiento que puede lograr con esta omisión serán menores en comparación con el uso de la barrera de todos los subprocesos.

En Direct3D 10 no hay sincronización de subprocesos al escribir en groupshared, por lo que esto significa que cada subproceso está limitado a una sola ubicación en una matriz para escribir. Use el valor del sistema SV_GroupIndex para indexar en esta matriz al escribir para asegurarse de que no pueden colisionar dos subprocesos. En términos de lectura, todos los subprocesos tienen acceso a toda la matriz para leer.

struct GSData
{
    float4 Color;
    float Factor;
}

groupshared GSData data[5*5*1];

[numthreads(5,5,1)]
void main( uint index : SV_GroupIndex )
{
    data[index].Color = (float4)0;
    data[index].Factor = 2.0f;
    GroupMemoryBarrierWithGroupSync();
    ...
}

Embalaje

Empaqueta subcomponentes de vectores y escalares cuyo tamaño es lo suficientemente grande como para evitar el cruce de límites de registro. Por ejemplo, todos estos son válidos:

cbuffer MyBuffer
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c1);
    float1 Element3 : packoffset(c1.y);
}

No se pueden mezclar tipos de empaquetado.

Al igual que la palabra clave register, un packoffset puede ser específico de destino. El empaquetado de subcomponentes solo está disponible con la palabra clave packoffset, no con la palabra clave register. Dentro de una declaración de cbuffer, la palabra clave register se omite para los destinos de Direct3D 10, ya que se supone que es para la compatibilidad multiplataforma.

Los elementos empaquetados pueden superponerse y el compilador no dará ningún error o advertencia. En este ejemplo, Element2 y Element3 se superpondrán con Element1.x y Element1.y.

cbuffer MyBuffer
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c0);
    float1 Element3 : packoffset(c0.y);
}

Un ejemplo que usa packoffset es: HLSLWithoutFX10 Sample.