Sintaxe variável
Use as seguintes regras de sintaxe para declarar variáveis HLSL.
[Storage_Class] [Type_Modifier] Nome do tipo[Índice] [:semântica ] [: Packoffset] [: Registrar]; [Anotações] [= Initial_Value]
Parâmetros
-
Storage_Class
-
Modificadores de classe de armazenamento opcionais que dão ao compilador dicas sobre escopo e tempo de vida variáveis; Os modificadores podem ser especificados em qualquer ordem.
Valor Descrição externa Marcar uma variável global como uma entrada externa para o sombreador; Esta é a marcação padrão para todas as variáveis globais. Não pode ser combinado com estática. 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á quaisquer cálculos usados para produzir o valor atribuído a essa variável das seguintes maneiras: - As operações separadas são mantidas separadas. Por exemplo, quando uma operação mul and add pode ter sido fundida em uma operação louca, precisa 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. Onde a ordem das instruções pode ter sido embaralhada para melhorar o desempenho, precisa garante que o compilador preserve a ordem como 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 levam em conta valores NaN (não um número) e INF (infinito), precisa força os requisitos IEEE relativos aos valores NaN e INF a serem respeitados. Sem preciso, essas otimizações e operações matemáticas não são seguras para IEEE.
- Qualificar uma variável precisa não faz com que as operações que usam a variável precisas. Como precisa se propaga apenas para operações que contribuem para os valores atribuídos à variável precisaqualificada, fazer corretamente os cálculos desejados precisos pode ser complicado, então recomendamos que você marque as saídas do sombreador precisas 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 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 para tesselação mantenham costuras de patch impermeáveis ou correspondam 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)
{
operação é precisa porque contribui para o parâmetro preciso OutPos
OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );
}
compartilhou Marcar uma variável para partilha entre efeitos; Esta é uma dica para o compilador. grupocompartilhou Marque uma variável para memória compartilhada por 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 16kb, em D3D11 o tamanho máximo é de 32kb. Ver exemplos. estática 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 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); As variáveis globais são consideradas uniforme por padrão. volátil Marque uma variável que muda com frequência; Esta é uma dica para o compilador. Este 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 opcional de tipo variável.
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 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 modificador de tipo, o compilador usará column_major como o valor padrão.
-
Tipo
-
Qualquer tipo de HLSL listado em tipos de dados (DirectX HLSL).
-
Nome[Índice]
-
Cadeia de caracteres ASCII que identifica exclusivamente uma variável de sombreador. Para definir uma matriz opcional, use índice para o tamanho da matriz, que é um inteiro positivo = 1.
-
semântica
-
Informações opcionais de uso de parâmetros, usadas pelo compilador para vincular entradas e saídas de sombreador. Existem vários semânticos de predefinidos para sombreadores de vértice e pixel. O compilador ignora semânticas, a menos que elas sejam declaradas em uma variável global ou um parâmetro passado para um sombreador.
-
Packoffset
-
Palavra-chave opcional para empacotar manualmente constantes de sombreador. Consulte packoffset (DirectX HLSL).
-
Registe-se
-
Palavra-chave opcional para atribuir manualmente uma variável de sombreador a um registro específico. Consulte registrar (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 efeitos e ignorada pelo HLSL; Para ver a sintaxe mais detalhada, consulte sintaxe de anotação.
-
Initial_Value
-
Valor(es) inicial(is) opcional(is); o número de valores deve corresponder ao número de componentes em Tipo. Cada variável global marcada externa deve ser inicializada com um valor literal; Cada variável marcada estática deve ser inicializada com uma constante.
As variáveis globais que não são marcadas estática ou externa 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 reflection 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 ID3D11ShaderReflectionVariable::GetDesc método para obter a descrição da variável de sombreador e obter o valor inicial do DefaultValue membro 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 reflexo e definir o valor inicial. Por exemplo, você pode usar o ID3DX11EffectPass::Apply método.
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áveis 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};
Grupo compartilhado
O HLSL permite que threads de um sombreador de computação troquem valores por meio de memória compartilhada. O HLSL fornece primitivas 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 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 vivamente esta omissão pelas seguintes 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 alcançar com essa omissão serão menores em comparação com o uso da barreira all-thread.
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 SV_GroupIndex valor do sistema para indexar nessa matriz ao escrever para garantir que nenhum thread possa 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
Embale subcomponentes de vetores e escalares cujo tamanho seja grande o suficiente para evitar cruzar os limites do 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 alvo. A embalagem 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 Direct3D 10, pois supõe-se que seja para compatibilidade entre plataformas.
Os elementos compactados podem se sobrepor e o compilador não dará nenhum erro ou 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.