Compartilhar via


Sintaxe variável

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

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

Parâmetros

Storage_Class

Modificadores opcionais de classe de armazenamento que fornecem 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 Marque 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 static.
nointerpolation Não interpole as saídas de um sombreador de vértice, antes de passá-las para um sombreador de pixel.
precise A palavra-chave precise, 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, onde uma operação mul e add pode ter sido fundida em uma operação mad, precise força as operações a permanecerem separadas. Em vez disso, você deve usar explicitamente a função intrínseca mad.
  • A ordem das operações será mantida. Onde a ordem das instruções pode ter sido embaralhada para melhorar o desempenho, precise garante que o compilador preserve a ordem, conforme escrita.
  • As operações inseguras do IEEE são restritas. Onde 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) values, precise força os requisitos IEEE relacionados aos valores NaN e INF a serem respeitados. Sem precise, essas otimizações e operações matemáticas não são seguras para IEEE.
  • Qualificar uma variável precise não torna as operações que usam a variável precisas. Como precise se propaga apenas para operações que contribuem para os valores atribuídos à variável qualificada precise, tornar corretamente os cálculos desejados precise pode ser complicado, portanto, recomendamos que você marque as saídas do sombreador precise diretamente onde você as declara, seja em um campo de estrutura, em um parâmetro de saída ou no tipo de retorno da função de entrada. A capacidade de controlar otimizações dessa maneira mantém a invariância de resultados para a variável de saída modificada, desativando otimizações que podem afetar os resultados finais devido a diferenças nas diferenças de precisão acumuladas. É útil quando você deseja que os sombreadores de tesselação mantenham as vedações de patch à prova d'água ou correspondam a 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 precise OutPos
    OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );
    }
shared Marque uma variável para compartilhamento entre efeitos. Esta é uma dica para o compilador.
groupshared Marque uma variável para memória compartilhada em grupo de threads para sombreadores de computação. No D3D10, o tamanho total máximo de todas as variáveis com a classe de armazenamento groupshared é de 16 kb, no D3D11, o tamanho máximo é de 32 kb. Consulte os exemplos.
static Marque uma variável local para que ela seja inicializada uma vez e persista entre as 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 será visível para um aplicativo.
uniform Marque 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). As variáveis globais são consideradas uniform por padrão.
volatile Marque uma variável que muda com frequência. Esta é uma dica para o compilador. Esse modificador de classe de armazenamento só se aplica a uma variável local.
Observação: o compilador HLSL atualmente ignora esse modificador de classe de armazenamento.

Type_Modifier

Modificador de tipo de variável opcional.

Valor Descrição
const Marque uma variável que não pode ser alterada por um sombreador e, portanto, deve ser inicializada na declaração da variável. As variáveis globais são consideradas const por padrão (suprima esse comportamento fornecendo o sinalizador /Gec ao 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 de modificador de tipo, o compilador usará column_major como o valor padrão.

Type

Qualquer tipo de 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 index como o tamanho da matriz, que é um inteiro positivo = 1.

Semantic

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

Packoffset

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

Registrar

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

Anotação(õ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, consulte Sintaxe de anotação.

Initial_Value

Valor(es) inicial(is) facultativo(s). O número de valores deve corresponder ao número de componentes em Type. Cada variável global marcada como extern deve ser inicializada com um valor literal. Cada variável marcada como static deve ser inicializada com uma constante.

As variáveis globais que não são marcadas como static nem 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 do 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 tenha sido 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 a reflexão e definir o valor inicial. Por exemplo, você pode usar o método ID3DX11EffectPass::Apply .

Importante

O suporte para esse recurso foi removido no Direct3D 12, incluindo a capacidade de refletir inicializadores padrão.

Exemplos

Aqui estão vários exemplos de declarações de variável 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};

Group shared

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 (distorções ou frentes de onda) e a sincronização de barreira às vezes 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 estes motivos:

  • 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 menores, 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 é 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 dois threads não 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();
    ...
}

Embalagem

Empacote subcomponentes de vetores e escalares cujo tamanho é grande o suficiente para evitar o cruzamento de limites de registro. Por exemplo, todos estes 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 embalagem.

Como a palavra-chave register, um packoffset pode ser específico do destino. O empacotamento de subcomponentes só está disponível com a palavra-chave packoffset, não com a palavra-chave register. Dentro de uma declaração cbuffer, a palavra-chave register é ignorada para destinos do Direct3D 10, pois é considerada para compatibilidade entre plataformas.

Os elementos empacotados podem se sobrepor e o compilador não fornecerá nenhum erro nem aviso. Neste exemplo, Element2 e Element3 se sobreporão 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 é: HLSLWithoutFX10 Sample.