Sintaxe de Variável

Use as regras de sintaxe a seguir para declarar variáveis HLSL.

[Storage_Class] [Type_Modifier] Type Name[Index] [: Semântico] [: Packoffset] [: Register]; [Anotações] [= Initial_Value]

Parâmetros

Storage_Class

Modificadores opcionais de classe de armazenamento que dão ao compilador dicas sobre o escopo e o tempo de vida da variável; os modificadores podem ser especificados em qualquer ordem.

Valor Descrição
extern Marcar uma variável global como uma entrada externa para o sombreador; essa é a marcação padrão para todas as variáveis globais. Não pode ser combinado com estático.
nointerpolation Não interpole as saídas de um sombreador de vértice antes de passá-las para um sombreador de pixel.
Preciso A palavra-chave precisa quando aplicada a uma variável restringirá todos os cálculos usados para produzir o valor atribuído a essa variável das seguintes maneiras:
  • Operações separadas são mantidas separadas. Por exemplo, quando uma mula e uma operação de adição podem ter sido fundidas em uma operação louca, a precisão força as operações a permanecerem separadas. Em vez disso, você deve usar explicitamente a função intrínseca louca.
  • A ordem das operações é mantida. Quando a ordem das instruções pode ter sido embaralhada para melhorar o desempenho, precisa garante que o compilador preserve a ordem conforme gravado.
  • As operações não seguras do IEEE são restritas. Quando o compilador pode ter usado operações matemáticas rápidas que não são responsáveis por valores NaN (não um número) e INF (infinito), o preciso força os requisitos do IEEE relativos a valores NaN e INF a serem respeitados. Sem precisão, essas otimizações e operações matemáticas não são seguras para IEEE.
  • Qualificar uma variável precisa não torna as operações que usam a variável precisas. Como a propagação precisa apenas para operações que contribuem para os valores atribuídos à variável qualificada com precisão, fazer cálculos desejados com precisão pode ser complicado, portanto, recomendamos que você marque as saídas do sombreador com precisão diretamente onde você as declara, seja em um campo de estrutura ou em um parâmetro de saída, ou o tipo de retorno da função de entrada. A capacidade de controlar otimizações dessa forma mantém a invariância de resultado para a variável de saída modificada desabilitando otimizações que podem afetar os resultados finais devido a diferenças nas diferenças de precisão acumuladas. É útil quando você deseja sombreadores para mosaico para manter costuras de patch apertadas ou corresponder valores de profundidade em várias passagens. Código de exemplo:
    HLSLmatrix g_mWorldViewProjection;
    void main(in float3 InPos : Position, out precise float4 OutPos : SV_Position)
    {
    a operação é precisa porque contribui para o parâmetro preciso OutPos
    OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );
    }
shared Marcar uma variável para compartilhar entre efeitos; essa é uma dica para o compilador.
groupshared Marque uma variável para memória compartilhada do grupo de threads para sombreadores de computação. Em D3D10, o tamanho total máximo de todas as variáveis com a classe de armazenamento groupshared é de 16 kb, em D3D11 o tamanho máximo é de 32 kb. Veja exemplos.
static Marque uma variável local para que ela seja inicializada uma vez e persista entre chamadas de função. Se a declaração não incluir um inicializador, o valor será definido como zero. Uma variável global marcada como estática não é visível para um aplicativo.
Uniforme Marcar uma variável cujos dados são constantes durante toda a execução de um sombreador (como uma cor de material em um sombreador de vértice); variáveis globais são consideradas uniformes por padrão.
volatile Marcar uma variável que é alterada com frequência; essa é uma dica para o compilador. Esse modificador de classe de armazenamento só se aplica a uma variável local.
Nota: O compilador HLSL atualmente ignora esse modificador de classe de armazenamento.

Type_Modifier

Modificador de tipo variável opcional.

Valor Descrição
const Marque uma variável que não pode ser alterada por um sombreador, portanto, ela deve ser inicializada na declaração de variável. As variáveis globais são consideradas const por padrão (suprima esse comportamento fornecendo o sinalizador /Gec para o compilador).
row_major Marque uma variável que armazena quatro componentes em uma única linha para que eles possam ser armazenados em um único registro constante.
column_major Marque uma variável que armazena 4 componentes em uma única coluna para otimizar a matemática da matriz.

Observação

Se você não especificar um valor modificador de tipo, o compilador usará column_major como o valor padrão.

Type

Qualquer tipo HLSL listado em Tipos de Dados (DirectX HLSL).

Name[Index]

Cadeia de caracteres ASCII que identifica exclusivamente uma variável de sombreador. Para definir uma matriz opcional, use o índice para o tamanho da matriz, que é um inteiro positivo = 1.

Semântica

Informações opcionais de uso de parâmetro, usadas pelo compilador para vincular entradas e saídas do sombreador. Há várias semânticas predefinidas para sombreadores de vértice e pixel. O compilador ignora a semântica, a menos que elas sejam declaradas em uma variável global ou um parâmetro passado para um sombreador.

Packoffset

Palavra-chave opcionais para empacotar constantes de sombreador manualmente. Consulte packoffset (DirectX HLSL).

Registrar

Palavra-chave opcionais para atribuir manualmente uma variável de sombreador a um registro específico. Consulte register (DirectX HLSL).

Anotações

Metadados opcionais, na forma de uma cadeia de caracteres, anexados a uma variável global. Uma anotação é usada pela estrutura de efeito e ignorada pelo HLSL; para ver a sintaxe mais detalhada, confira sintaxe de anotação.

Initial_Value

Valores iniciais opcionais; o número de valores deve corresponder ao número de componentes em Tipo. Cada variável global marcada como extern deve ser inicializada com um valor literal; cada variável marcada como estática deve ser inicializada com uma constante.

Variáveis globais que não estão marcadas como estáticas ou extern não são compiladas no sombreador. O compilador não define automaticamente valores padrão para variáveis globais e não pode usá-los em otimizações. Para inicializar esse tipo de variável global, use reflexão para obter seu valor e, em seguida, copie o valor para um buffer constante. Por exemplo, você pode usar o método ID3D11ShaderReflection::GetVariableByName para obter a variável, usar o método ID3D11ShaderReflectionVariable::GetDesc para obter a descrição da variável de sombreador e obter o valor inicial do membro DefaultValue da estrutura D3D11_SHADER_VARIABLE_DESC . Para copiar o valor para o buffer constante, você deve garantir que o buffer foi criado com acesso de gravação da CPU (D3D11_CPU_ACCESS_WRITE). Para obter mais informações sobre como criar um buffer constante, consulte Como criar um buffer constante.

Você também pode usar a estrutura de efeitos para processar automaticamente o refletindo e definindo o valor inicial. Por exemplo, você pode usar o método ID3DX11EffectPass::Apply .

Exemplos

Aqui estão vários exemplos de declarações de variável de sombreador.

float fVar;
float4 color;
float fVar = 3.1f;

int iVar[3];

int iVar[3] = {1,2,3};

uniform float4 position : SV_POSITION; 
const float4 lightDirection = {0,0,1};
      

Agrupar Compartilhado

O HLSL permite que threads de um sombreador de computação troquem valores por meio da memória compartilhada. O HLSL fornece primitivos de barreira, como GroupMemoryBarrierWithGroupSync, e assim por diante para garantir a ordenação correta de leituras e gravações na memória compartilhada no sombreador e evitar corridas de dados.

Observação

O hardware executa threads em grupos (warps ou frentes de onda) e, às vezes, a sincronização de barreiras pode ser omitida para aumentar o desempenho quando apenas a sincronização de threads que pertencem ao mesmo grupo está correta. Mas desencorajamos essa omissão por estas razões:

  • Essa omissão resulta em código não portátil, que pode não funcionar em algum hardware e não funciona em rasterizadores de software que normalmente executam threads em grupos menores.
  • As melhorias de desempenho que você pode obter com essa omissão serão secundárias em comparação com o uso da barreira de todos os threads.

No Direct3D 10, não há sincronização de threads ao gravar em groupshared, portanto, isso significa que cada thread está limitado a um único local em uma matriz para gravação. Use o valor do sistema SV_GroupIndex para indexar nessa matriz ao gravar para garantir que nenhum dois threads possam colidir. Em termos de leitura, todos os threads têm acesso a toda a matriz para leitura.

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();
    ...
}

Empacotamento

Empacote subcomponentes de vetores e escalares cujo tamanho é grande o suficiente para evitar a passagem de limites de registro. Por exemplo, todos eles são válidos:

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

Não é possível misturar tipos de empacotamento.

Assim como o palavra-chave de registro, um packoffset pode ser específico de destino. O empacotamento de subcomponente só está disponível com o packoffset palavra-chave, não com o palavra-chave de registro. Dentro de uma declaração cbuffer, o registro palavra-chave é ignorado para destinos do Direct3D 10, pois supõe-se que seja para compatibilidade entre plataformas.

Os elementos empacotados podem se sobrepor e o compilador não fornecerá nenhum erro ou aviso. Neste exemplo, Element2 e Element3 se sobrepõem a Element1.x e Element1.y.

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

Um exemplo que usa packoffset é: Exemplo de HLSLWithoutFX10.

Variáveis (DirectX HLSL)