Vinculação de Sombreador de Efeito

Direct2D usa uma otimização chamada vinculação de sombreador de efeito que combina várias passagens de renderização de grafo de efeito em uma única passagem.

Visão geral da vinculação do sombreador de efeito

As otimizações de vinculação de sombreador de efeito se baseiam na vinculação do sombreador HLSL, um recurso direct3D 11.2 que permite que sombreadores de pixel e vértice sejam gerados em runtime vinculando funções de sombreador pré-compiladas. As figuras a seguir ilustram o conceito de vinculação de sombreador de efeito em um grafo de efeito. A primeira figura mostra um grafo de efeito Direct2D típico com quatro transformações de renderização. Sem a vinculação do sombreador, cada transformação consome uma passagem de renderização e requer uma superfície intermediária; no total, esse grafo requer 4 passes e 3 intermediários.

transformar grafo sem vinculação de sombreador: 4 passes e 3 intermediários.

A segunda figura mostra o mesmo grafo de efeito em que cada transformação de renderização foi substituída por uma versão de função vinculável. Direct2D é capaz de vincular todo o grafo e executá-lo em uma passagem sem a necessidade de intermediários. Isso pode fornecer uma redução significativa no tempo de execução da GPU e redução no consumo de memória de GPU de pico.

transformar grafo com vinculação de sombreador: 1 passagem, 0 intermediários.

 

A vinculação do sombreador de efeito opera em transformações individuais dentro de um efeito; isso significa que até mesmo um grafo com um único efeito poderá se beneficiar da vinculação do sombreador se esse efeito tiver várias transformações válidas.

Usando a vinculação do sombreador de efeito

Se você estiver criando um aplicativo Direct2D que usa efeitos, não precisará fazer nada para aproveitar a vinculação do sombreador de efeito. Direct2D analisa automaticamente o grafo de efeito para determinar a maneira mais ideal de vincular cada transformação.

Os autores de efeitos são responsáveis por implementar seu efeito de forma a dar suporte à vinculação do sombreador de efeito; para obter mais informações, consulte a seção Criação de um efeito personalizado compatível com vinculação de sombreador abaixo. Todos os efeitos internos dão suporte à vinculação de sombreador.

Direct2D vinculará apenas transformações de renderização adjacentes em situações em que ela é benéfica. Ele leva em conta vários fatores ao determinar se é necessário vincular duas transformações. Por exemplo, a vinculação de sombreador não será executada se uma das transformações usar sombreadores de vértice ou de computação, pois somente sombreadores de pixel poderão ser vinculados. Além disso, se um efeito não tiver sido criado para ser compatível com a vinculação do sombreador, as transformações ao redor não serão vinculadas a ele.

Caso esse risco de vinculação exista, Direct2D não vinculará nenhuma transformação adjacente ao risco, mas ainda tentará vincular o restante do grafo.

transformar grafo com um risco de vinculação: 2 passes, 1 intermediário.

Criação de um efeito personalizado compatível com vinculação de sombreador

Se você estiver criando seu próprio efeito de Direct2D personalizado, precisará garantir que suas transformações ofereçam suporte à vinculação do sombreador de efeito. Isso requer algumas pequenas alterações de como os efeitos personalizados anteriores foram implementados. Se uma transformação em seu efeito personalizado não der suporte à vinculação de sombreador, Direct2D não a vinculará a nenhuma transformação adjacente a ela no grafo de efeito.

Como autor de efeito personalizado, você deve estar ciente de vários conceitos e requisitos importantes:

  • Nenhuma alteração nas implementações de interface de efeito

    Você não precisa modificar nenhum código que implemente as várias interfaces de efeito, como ID2D1DrawTransform.

  • Fornecer uma versão de função completa e de exportação de sombreadores

    Você deve fornecer uma versão de função de exportação dos sombreadores do efeito que podem ser vinculados por Direct2D. Além disso, você também deve continuar a fornecer o sombreador original e completo; isso ocorre porque Direct2D seleciona em runtime a versão certa do sombreador, dependendo se a vinculação do sombreador deve ser aplicada a um link específico no grafo.

    Se uma transformação fornecer apenas o blob de sombreador de pixel completo (via ID2D1EffectContext::LoadPixelShader), ela não será vinculada a transformações adjacentes.

  • Funções auxiliares

    Direct2D fornece funções auxiliares HLSL e macros que gerarão automaticamente as versões completas e de função de exportação de um sombreador. Esses auxiliares podem ser encontrados em d2d1effecthelpers.hlsli. Além disso, o compilador HLSL (FXC) permite inserir o sombreador de função de exportação em um campo privado no sombreador completo. Dessa forma, você só precisa criar um sombreador uma vez e passar ambas as versões para Direct2D simultaneamente. Tanto d2d1effecthelpers.hlsli quanto o compilador FXC são incluídos como parte do SDK do Windows.

    As funções auxiliares:

    Você também pode criar manualmente duas versões de cada sombreador e compilá-las duas vezes, desde que as especificações descritas abaixo em Exportar especificações de função sejam atendidas .

  • Somente sombreadores de pixel

    Direct2D não dá suporte à vinculação de sombreadores de computação ou vértice. No entanto, se o efeito usar um sombreador de vértice e pixel, a saída do sombreador de pixel ainda poderá ser vinculada.

  • Amostragem simples versus complexa

    A vinculação da função de sombreador funciona conectando a saída de uma passagem de sombreador de pixel à entrada de uma passagem de sombreador de pixel subsequente. Isso só é possível quando o sombreador de pixel de consumo requer apenas um único valor de entrada para executar sua computação; esse valor normalmente viria da amostragem de uma textura de entrada na coordenada de textura emitida pelo sombreador de vértice. Esse sombreador de pixel é dito para executar amostragem simples.

    conversão em escala de cinza é um exemplo de amostragem simples. o valor de um pixel de saída específico depende apenas do valor do pixel de entrada correspondente.

    Alguns sombreadores de pixel, como um desfoque gaussiano, calculam sua saída de várias amostras de entrada em vez de apenas uma única amostra. Esse sombreador de pixel é dito para executar amostragem complexa.

    gaussian blur é um exemplo de amostragem complexa. o valor do pixel de saída central depende de vários pixels de entrada.

    Somente funções de sombreador com entradas simples podem ter sua entrada fornecida por outra função de sombreador. As funções de sombreador com entradas complexas devem ser fornecidas com uma textura de entrada para amostragem. Isso significa que Direct2D não vinculará um sombreador com entradas complexas ao seu antecessor.

    Ao usar os auxiliares HLSL Direct2D, você deve indicar no HLSL se um sombreador usa entradas complexas ou simples.

Exemplo de sombreador de efeito compatível com vinculação

Usando os auxiliares D2D, o snippet de código a seguir representa um sombreador de efeito compatível com vinculação simples:

#define D2D_INPUT_COUNT 1
#define D2D_INPUT0_SIMPLE
#include “d2d1effecthelpers.hlsli”

D2D_PS_ENTRY(LinkingCompatiblePixelShader)
{
    float4 input = D2DGetInput(0);
    input.rgb *= input.a;
    return input;
}          

Neste breve exemplo, observe que nenhum parâmetro de função é declarado, que o número de entradas e o tipo de cada entrada é declarado antes da função de entrada, a entrada é recuperada chamando D2DGetInput e que as diretivas de pré-processador devem ser definidas antes que o arquivo auxiliar seja incluído.

Um sombreador compatível com vinculação deve fornecer um sombreador de pixel de passagem única regular e uma função de sombreador de exportação. A macro D2D_PS_ENTRY permite que cada uma delas seja gerada a partir do mesmo código, quando usada em conjunto com o script de compilação do sombreador.

Ao compilar um sombreador completo, as macros são expandidas para o código a seguir, que tem uma assinatura de entrada compatível com efeitos D2D.

Texture2D<float4> InputTexture0;
SamplerState InputSampler0;

float4 LinkingCompatiblePixelShader(
    float4 pos   : SV_POSITION,
    float4 posScene : SCENE_POSITION,
    float4 uv0  : TEXCOORD0
    ) : SV_Target
    {
        float4 input = InputTexture0.Sample(InputSampler0, uv0.xy);
        input.rgb *= input.a;
        return input;
    }    

Ao compilar uma versão de função de exportação do mesmo código, o código a seguir é gerado:

// Shader function version
export float4 LinkingCompatiblePixelShader_Function(
    float4 input0 : INPUT0)
    {
        input.rgb *= input.a;
        return input;
    }      

Observe que a entrada de textura, normalmente recuperada pela amostragem de um Texture2D, foi substituída por uma entrada de função (input0).

Para ver uma descrição completa e passo a passo do que você precisa fazer para escrever um efeito compatível com vinculação, consulte o tutorial Efeitos personalizados e o exemplo Direct2D efeitos de imagem personalizados.

Compilando um sombreador compatível de vinculação

Para ser vinculável, o blob de sombreador de pixel passado para D2D deve conter as versões completas e de função de exportação do sombreador. Isso é feito inserindo a função de exportação compilada na área D3D_BLOB_PRIVATE_DATA.

Quando os sombreadores são criados com as funções auxiliares D2D, um destino de compilação D2D deve ser definido no momento da compilação. Os tipos de destino de compilação são D2D_FULL_SHADER e D2D_FUNCTION.

Compilar um sombreador de efeito compatível com vinculação é um processo de duas etapas:

Observação

Ao compilar um efeito usando o Visual Studio, você deve criar um arquivo em lote que execute os dois comandos FXC e execute esse arquivo em lote como uma etapa de build personalizada executada antes da etapa de compilação.

 

Etapa 1: Compilar a função de exportação

fxc /T <shadermodel> <MyShaderFile>.hlsl /D D2D_FUNCTION /D D2D_ENTRY=<entry> /Fl <MyShaderFile>.fxlib           

Para compilar a versão da função de exportação do sombreador, você deve passar os sinalizadores a seguir para FXC.

Sinalizador Descrição
/T <ShaderModel> Defina <ShaderModel> como o perfil de sombreador de pixel apropriado, conforme definido na sintaxe FXC. Esse deve ser um dos perfis listados em "Vinculação de sombreador HLSL".
<MyShaderFile.hlsl> Defina <MyShaderFile> como o nome do arquivo HLSL.
/D D2D_FUNCTION Essa definição instrui o FXC a compilar a versão da função de exportação do sombreador.
/D D2D_ENTRY=<entry> Defina <a entrada> como o nome do ponto de entrada HLSL definido dentro da macro D2D_PS_ENTRY .
/Fl <MyShaderFile.fxlib> Defina <MyShaderfile> como onde você deseja armazenar a versão da função de exportação do sombreador. Observe que a extensão .fxlib é apenas para facilitar a identificação.

Etapa 2: compilar o sombreador completo e inserir a função de exportação

fxc /T ps_<shadermodel> <MyShaderFile>.hlsl /D D2D_FULL_SHADER /D D2D_ENTRY=<entry> /E <entry> /setprivate <MyShaderFile>.fxlib /Fo <MyShader>.cso /Fh <MyShader>.h           

Para compilar a versão completa do sombreador com a versão de exportação inserida, você deve passar os sinalizadores a seguir para o FXC.

Sinalizador Descrição
/T <ShaderModel> Defina <ShaderModel> como o perfil de sombreador de pixel apropriado, conforme definido na sintaxe FXC. Esse deve ser o perfil de sombreador de pixel correspondente ao perfil de vinculação especificado na Etapa 1.
<MyShaderFile.hlsl> Defina <MyShaderFile> como o nome do arquivo HLSL.
/D D2D_FULL_SHADER Essa definição instrui o FXC a compilar a versão completa do sombreador.
/D D2D_ENTRY=<entry> Defina <a entrada> como o nome do ponto de entrada HLSL definido dentro da macro D2D_PS_ENTRY().
Entrada /E <> Defina <a entrada> como o nome do ponto de entrada HLSL definido dentro da macro D2D_PS_ENTRY().
/setprivate <MyShaderFile.fxlib> Esse argumento instrui o FXC a inserir o sombreador de função de exportação gerado na etapa 1 na área D3D_BLOB_PRIVATE_DATA.
/Fo <MyShader.cso> Defina <MyShader> como onde você deseja armazenar o sombreador compilado final e combinado.
/Fh <MyShader.h> Defina <MyShader> como onde você deseja armazenar o cabeçalho final combinado.

Exportar especificações de função

É possível, embora não recomendado, criar um sombreador de efeito compatível sem usar os auxiliares fornecidos por D2D. É necessário ter cuidado para garantir que o sombreador completo e as assinaturas de entrada da função de exportação estejam em conformidade com as especificações D2D.

As especificações para sombreadores completos são as mesmas das versões anteriores do Windows. Resumidamente, os parâmetros de entrada do sombreador de pixel devem ser SV_POSITION, SCENE_POSITION e uma entrada TEXCOORD por efeito.

Para a função de exportação, a função deve retornar um float4 e suas entradas devem ser um dos seguintes tipos:

  • Entrada simples

    float4 d2d_inputN : INPUTN         
    

    Para entradas simples, d2D inserirá uma função de exemplo entre a textura de entrada e a função de sombreador ou a entrada será fornecida pela saída de outra função de sombreador.

  • Entrada complexa

    float4 d2d_uvN  : TEXCOORDN                
    

    Para entradas complexas, o D2D passará apenas uma coordenada de textura, conforme descrito em Windows 8 documentação.

  • local de saída

    float4 d2d_posScene : SCENE_POSITION                
    

    Somente uma SCENE_POSITION entrada pode ser definida. Esse parâmetro só deve ser incluído quando necessário, pois apenas uma função por sombreador vinculado pode utilizar esse parâmetro.

A semântica deve ser definida como acima, pois o D2D inspecionará a semântica para decidir como vincular funções. Se qualquer entrada de função não corresponder a um dos tipos acima, a função será rejeitada para vinculação de sombreador.

Auxiliares do HLSL

Interface ID3D11Linker

Interface ID3D11FunctionLinkingGraph