Organizando estado em um efeito (Direct3D 11)

Com o Direct3D 11, o estado de efeito para determinados estágios de pipeline é organizado por estruturas. Aqui estão as estruturas:

Estado do pipeline Estrutura
Rasterization D3D11_RASTERIZER_DESC
Fusão de saída D3D11_BLEND_DESC e D3D11_DEPTH_STENCIL_DESC
Sombreadores Veja abaixo

 

Para os estágios do sombreador, em que o número de alterações de estado precisa ser mais controlado por um aplicativo, o estado foi dividido em estado de buffer constante, estado do sampler, estado do recurso de sombreador e estado de exibição de acesso não ordenado (para sombreadores de pixel e computação). Isso permite que um aplicativo projetado cuidadosamente atualize apenas o estado que está mudando, o que melhora o desempenho reduzindo a quantidade de dados que precisam ser passados para a GPU.

Então, como você organiza o estado do pipeline em um efeito?

A resposta é que a ordem não importa. As variáveis globais não precisam estar localizadas na parte superior. No entanto, todos os exemplos no SDK seguem a mesma ordem, pois é uma boa prática organizar os dados da mesma maneira. Portanto, esta é uma breve descrição da ordenação de dados nos exemplos do SDK do DirectX.

Variáveis globais

Assim como a prática C padrão, as variáveis globais são declaradas primeiro, na parte superior do arquivo. Na maioria das vezes, essas são variáveis que serão inicializadas por um aplicativo e, em seguida, usadas em um efeito . Às vezes, eles são inicializados e nunca alterados, outras vezes são atualizados a cada quadro. Assim como as regras de escopo da função C, as variáveis de efeito declaradas fora do escopo das funções de efeito são visíveis durante todo o efeito; qualquer variável declarada dentro de uma função de efeito só é visível dentro dessa função.

Aqui está um exemplo das variáveis declaradas em BasicHLSL10.fx.

// Global variables
float4 g_MaterialAmbientColor;      // Material's ambient color

Texture2D g_MeshTexture;            // Color texture for mesh

float    g_fTime;                   // App's time in seconds
float4x4 g_mWorld;                  // World matrix for object
float4x4 g_mWorldViewProjection;    // World * View * Projection matrix


// Texture samplers
SamplerState MeshTextureSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

A sintaxe para variáveis de efeito é mais detalhada em Sintaxe de Variável de Efeito (Direct3D 11). A sintaxe para amostradores de textura de efeito é mais detalhada em Tipo de Amostra (DirectX HLSL).

Sombreadores

Sombreadores são pequenos programas executáveis. Você pode considerar sombreadores como estado de sombreador encapsulador, já que o código HLSL implementa a funcionalidade do sombreador. Os gráficos pipeline até cinco tipos diferentes de sombreadores.

  • Sombreadores de vértice – operar em dados de vértice. Um vértice em produz um vértice.
  • Sombreadores de casco – operar em dados de patch. Fase do Ponto de Controle: uma invocação produz um ponto de controle; Para cada Fases de Bifurcação e Junção: um patch produz alguma quantidade de dados constantes de patch.
  • Sombreadores de domínio – operar em dados primitivos. Um primitivo pode produzir 0, 1 ou muitos primitivos.
  • Sombreadores de geometria – operar em dados primitivos. Um primitivo em pode produzir 0, 1 ou muitos primitivos fora.
  • Sombreadores de pixel – opere em dados de pixel. Um pixel em produz 1 pixel para fora (a menos que o pixel seja retirado de uma renderização).

O pipeline do sombreador de computação usa um sombreador:

  • Sombreadores de computação – opere em qualquer tipo de dados. A saída é independente do número de threads.

Sombreadores são funções locais e seguem regras de função de estilo C. Quando um efeito é compilado, cada sombreador é compilado e um ponteiro para cada função de sombreador é armazenado internamente. Uma interface ID3D11Effect é retornada quando a compilação é bem-sucedida. Neste ponto, o efeito compilado está em um formato intermediário.

Para saber mais sobre os sombreadores compilados, você precisará usar a reflexão do sombreador. Isso é essencialmente como pedir ao runtime para descompilar os sombreadores e retornar informações sobre o código do sombreador.

struct VS_OUTPUT
{
    float4 Position   : SV_POSITION; // vertex position 
    float4 Diffuse    : COLOR0;      // vertex diffuse color
    float2 TextureUV  : TEXCOORD0;   // vertex texture coords 
};

VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
                         float3 vNormal : NORMAL,
                         float2 vTexCoord0 : TEXCOORD,
                         uniform int nNumLights,
                         uniform bool bTexture,
                         uniform bool bAnimate )
{
    VS_OUTPUT Output;
    float3 vNormalWorldSpace;
 
    ....    
    
    return Output;    
}


struct PS_OUTPUT
{
    float4 RGBColor : SV_Target;  // Pixel color
};

PS_OUTPUT RenderScenePS( VS_OUTPUT In,
                         uniform bool bTexture ) 
{ 
    PS_OUTPUT Output;

    if( bTexture )
        Output.RGBColor = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV) * In.Diffuse;
    ....

    return Output;
}

A sintaxe para sombreadores de efeito é mais detalhada na Sintaxe de Função de Efeito (Direct3D 11).

Grupos, técnicas e passagens

Um grupo é uma coleção de técnicas. Uma técnica é uma coleção de passes de renderização (deve haver pelo menos uma passagem). Cada passagem de efeito (que é semelhante no escopo a uma única passagem em um loop de renderização) define o estado do sombreador e qualquer outro estado de pipeline necessário para renderizar a geometria.

Os grupos são opcionais. Há um único grupo sem nome que abrange todas as técnicas globais. Todos os outros grupos devem ser nomeados.

Aqui está um exemplo de uma técnica (que inclui uma passagem) de BasicHLSL10.fx.

technique10 RenderSceneWithTexture1Light
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, RenderSceneVS( 1, true, true ) ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, RenderScenePS( true ) ) );
    }
}

fxgroup g0
{
    technique11 RunComputeShader
    {
        pass P0
        {
            SetComputeShader( CompileShader( cs_5_0, CS() ) );
        }
    }
}

A sintaxe para sombreadores de efeito é mais detalhada na Sintaxe de Técnica de Efeito (Direct3D 11).

Efeitos (Direct3D 11)