Collegamento degli shader degli effetti

Direct2D usa un'ottimizzazione denominata collegamento di effect shader che combina il rendering di più effetti del grafico passa in un singolo passaggio.

Panoramica del collegamento degli shader degli effetti

L'effetto shader che collega le ottimizzazioni si basa sul collegamento dello shader HLSL, una funzionalità Direct3D 11.2 che consente di generare pixel e vertex shader in fase di esecuzione collegando le funzioni shader precompilata. Le figure seguenti illustrano il concetto di collegamento dello shader degli effetti in un grafico degli effetti. La prima figura mostra un tipico grafico degli effetti Direct2D con quattro trasformazioni di rendering. Senza il collegamento dello shader, ogni trasformazione utilizza un passaggio di rendering e richiede una superficie intermedia; in totale, questo grafico richiede 4 passaggi e 3 intermedi.

trasformare il grafo senza collegamento dello shader: 4 passaggi e 3 intermedi.

La seconda figura mostra lo stesso grafico degli effetti in cui ogni trasformazione di rendering è stata sostituita con una versione della funzione collegabile. Direct2D è in grado di collegare l'intero grafico ed eseguirlo in un unico passaggio senza richiedere alcun livello intermedio. Ciò può offrire una riduzione significativa del tempo di esecuzione della GPU e della riduzione del picco del consumo di memoria GPU.

trasformare il grafo con collegamento shader: 1 passaggio, 0 intermedi.

 

Il collegamento di effect shader opera sulle singole trasformazioni all'interno di un effetto; Ciò significa che anche un grafico con un singolo effetto può trarre vantaggio dal collegamento dello shader se tale effetto ha più trasformazioni valide.

Uso del collegamento degli shader degli effetti

Se si sta creando un'applicazione Direct2D che usa gli effetti, non è necessario eseguire alcuna operazione per sfruttare i vantaggi del collegamento dello shader degli effetti. Direct2D analizza automaticamente il grafico degli effetti per determinare il modo più ottimale per collegare ogni trasformazione.

Gli autori di effetti sono responsabili dell'implementazione del loro effetto in modo da supportare il collegamento degli shader degli effetti; per altre informazioni, vedere la sezione Creazione di un effetto personalizzato compatibile con il collegamento di uno shader di seguito. Tutti gli effetti predefiniti supportano il collegamento dello shader.

Direct2D collega solo le trasformazioni di rendering adiacenti in situazioni in cui è vantaggioso. Tiene conto di più fattori quando si determina se collegare due trasformazioni. Ad esempio, il collegamento dello shader non viene eseguito se una delle trasformazioni usa vertex o compute shader, in quanto è possibile collegare solo pixel shader. Inoltre, se non è stato creato un effetto per essere compatibile con il collegamento di shader, le trasformazioni circostanti non verranno collegate.

Nel caso in cui esista un rischio di collegamento di questo tipo, Direct2D non collega alcuna trasformazione adiacente al pericolo, ma tenterà comunque di collegare il resto del grafico.

trasformare il grafico con un pericolo di collegamento: 2 passaggi, 1 intermedio.

Creazione di un effetto personalizzato compatibile con il collegamento di uno shader

Se si sta creando un effetto Direct2D personalizzato, è necessario assicurarsi che le sue trasformazioni supportino il collegamento degli shader degli effetti. Ciò richiede alcune modifiche minime rispetto alla modalità di implementazione degli effetti personalizzati precedenti. Se una trasformazione all'interno dell'effetto personalizzato non supporta il collegamento di shader, Direct2D non lo collega ad alcuna trasformazione adiacente nel grafico degli effetti.

In qualità di autore di effetti personalizzati, è necessario conoscere diversi concetti e requisiti chiave:

  • Nessuna modifica alle implementazioni dell'interfaccia

    Non è necessario modificare codice che implementa le varie interfacce degli effetti, ad esempio ID2D1DrawTransform.

  • Specificare sia una versione completa che la versione della funzione di esportazione degli shader

    È necessario fornire una versione della funzione di esportazione degli shader dell'effetto collegabili da Direct2D. Inoltre, è necessario continuare a fornire l'originale, full shader; questo perché Direct2D seleziona in fase di esecuzione la versione dello shader corretta a seconda che il collegamento dello shader venga applicato a un collegamento specifico nel grafico.

    Se una trasformazione fornisce solo il BLOB pixel shader completo (tramite ID2D1EffectContext::LoadPixelShader), non verrà collegato a trasformazioni adiacenti.

  • Funzioni helper

    Direct2D fornisce funzioni helper HLSL e macro che genereranno automaticamente sia le versioni complete che le versioni delle funzioni di esportazione di uno shader. Questi helper sono disponibili in d2d1effecthelpers.hlsli. Inoltre, il compilatore HLSL (FXC) consente di inserire lo shader della funzione di esportazione in un campo privato nello shader completo. In questo modo, è sufficiente creare uno shader una sola volta e passare entrambe le versioni a Direct2D contemporaneamente. Sia d2d1effecthelpers.hlsli che il compilatore FXC sono inclusi come parte di Windows SDK.

    Le funzioni helper:

    È anche possibile creare manualmente due versioni di ogni shader e compilarle due volte, purché vengano soddisfatte le specifiche descritte di seguito in Esportare le specifiche della funzione .

  • Solo pixel shader

    Direct2D non supporta il collegamento di compute o vertex shader. Tuttavia, se l'effetto usa sia un vertice che un pixel shader, l'output del pixel shader può comunque essere collegato.

  • Campionamento semplice e complesso

    Il collegamento della funzione shader funziona connettendo l'output di un pixel shader pass all'input di un passaggio pixel shader successivo. Ciò è possibile solo quando l'utilizzo del pixel shader richiede solo un singolo valore di input per eseguire il calcolo; questo valore in genere deriva dal campionamento di una trama di input in corrispondenza della coordinata della trama generata dal vertex shader. Si dice che un pixel shader di questo tipo esegua un campionamento semplice.

    la conversione in scala di grigi è un esempio di campionamento semplice. il valore di un pixel di output specifico dipende solo dal valore del pixel di input corrispondente.

    Alcuni pixel shader, ad esempio una sfocatura gaussiana, calcolano l'output da più esempi di input anziché solo un singolo esempio. Si dice che un pixel shader di questo tipo esegua un campionamento complesso.

    la sfocatura gaussiana è un esempio di campionamento complesso. il valore del pixel di output centrale dipende da più pixel di input.

    Solo le funzioni shader con input semplici possono avere l'input fornito da un'altra funzione shader. Le funzioni shader con input complessi devono essere fornite con una trama di input da campionare. Ciò significa che Direct2D non collecherà uno shader con input complessi al predecessore.

    Quando si usano gli helper Direct2D HLSL, è necessario indicare in HLSL se uno shader usa input complessi o semplici.

Esempio di collegamento compatibile con lo shader degli effetti

Usando gli helper D2D, il frammento di codice seguente rappresenta un semplice shader compatibile con il collegamento:

#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;
}          

In questo breve esempio si noti che non vengono dichiarati parametri di funzione, che il numero di input e il tipo di ogni input vengono dichiarati prima della funzione di immissione, l'input viene recuperato chiamando D2DGetInput e che le direttive del preprocessore devono essere definite prima che venga incluso il file helper.

Uno shader compatibile con il collegamento deve fornire sia un normale pixel shader a passaggio singolo che una funzione di esportazione shader. La macro D2D_PS_ENTRY consente di generare ognuno di questi elementi dallo stesso codice, se usato insieme allo script di compilazione dello shader.

Quando si compila uno shader completo, le macro vengono espanse nel codice seguente, con una firma di input compatibile con D2D Effects.

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;
    }    

Quando si compila una versione della funzione di esportazione dello stesso codice, viene generato il codice seguente:

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

Si noti che l'input della trama, normalmente recuperato dal campionamento di texture2D, è stato sostituito con un input di funzione (input0).

Per visualizzare una descrizione dettagliata di ciò che è necessario fare per scrivere un effetto compatibile con il collegamento, vedere l'esercitazione Effetti personalizzati e l'esempio di effetti immagine personalizzati Direct2D.

Compilazione di uno shader compatibile con collegamento

Per essere collegabile, il BLOB pixel shader passato a D2D deve contenere sia le versioni complete che le versioni delle funzioni di esportazione dello shader. Questa operazione viene eseguita incorporando la funzione di esportazione compilata nell'area D3D_BLOB_PRIVATE_DATA.

Quando gli shader vengono creati con le funzioni helper D2D, è necessario definire una destinazione di compilazione D2D in fase di compilazione. I tipi di destinazione di compilazione sono D2D_FULL_SHADER e D2D_FUNCTION.

La compilazione di uno shader degli effetti compatibile con il collegamento è un processo in due passaggi:

Nota

Quando si compila un effetto usando Visual Studio, è necessario creare un file batch che esegue entrambi i comandi FXC ed eseguire questo file batch come passaggio di compilazione personalizzato che viene eseguito prima del passaggio di compilazione.

 

Passaggio 1: Compilare la funzione di esportazione

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

Per compilare la versione della funzione di esportazione dello shader, è necessario passare i flag seguenti a FXC.

Flag Descrizione
/T <ShaderModel> Impostare <ShaderModel> sul profilo di pixel shader appropriato come definito nella sintassi FXC. Questo deve essere uno dei profili elencati in "Collegamento dello shader HLSL".
<MyShaderFile.hlsl> Impostare <MyShaderFile> sul nome del file HLSL.
/D D2D_FUNCTION Questa definizione indica a FXC di compilare la versione della funzione di esportazione dello shader.
/D D2D_ENTRY=<entry> Impostare <la voce sul nome del punto di ingresso> HLSL definito all'interno della macro D2D_PS_ENTRY .
/Fl <MyShaderFile.fxlib> Impostare <MyShaderfile> su dove si vuole archiviare la versione della funzione di esportazione dello shader. Si noti che l'estensione .fxlib è solo per facilitare l'identificazione.

Passaggio 2: Compilare il shader completo e incorporare la funzione di esportazione

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           

Per compilare la versione completa dello shader con la versione di esportazione incorporata, è necessario passare i flag seguenti a FXC.

Flag Descrizione
/T <ShaderModel> Impostare <ShaderModel> sul profilo di pixel shader appropriato come definito nella sintassi FXC. Questo deve essere il profilo pixel shader corrispondente al profilo di collegamento specificato nel passaggio 1.
<MyShaderFile.hlsl> Impostare <MyShaderFile> sul nome del file HLSL.
/D D2D_FULL_SHADER Questa definizione indica a FXC di compilare la versione completa del shader.
/D D2D_ENTRY=<entry> Impostare <la voce sul nome del punto di ingresso> HLSL definito all'interno della macro D2D_PS_ENTRY().
/E <voce> Impostare <la voce sul nome del punto di ingresso> HLSL definito all'interno della macro D2D_PS_ENTRY().
/setprivate <MyShaderFile.fxlib> Questo argomento indica a FXC di incorporare lo shader della funzione di esportazione generato nel passaggio 1 nell'area di D3D_BLOB_PRIVATE_DATA.
/Fo <MyShader.cso> Impostare <MyShader> su dove archiviare l'shader compilato combinato finale.
/Fh <MyShader.h> Impostare <MyShader> su dove archiviare l'intestazione finale combinata.

Esportare le specifiche delle funzioni

È possibile, anche se non è consigliabile, creare uno shader compatibile senza usare gli helper forniti da D2D. È necessario prestare attenzione per assicurarsi che le firme di input della funzione di esportazione e shader complete siano conformi alle specifiche D2D.

Le specifiche per i shader completi sono uguali alle versioni precedenti di Windows. Brevemente, i parametri di input del pixel shader devono essere SV_POSITION, SCENE_POSITION e un input TEXCOORD per effetto.

Per la funzione di esportazione, la funzione deve restituire un float4 e i relativi input devono essere uno dei tipi seguenti:

  • Input semplice

    float4 d2d_inputN : INPUTN         
    

    Per gli input semplici, D2D inserisce una funzione Sample tra la trama di input e la funzione shader oppure l'input verrà fornito dall'output di un'altra funzione shader.

  • Input complesso

    float4 d2d_uvN  : TEXCOORDN                
    

    Per gli input complessi, D2D passerà solo una coordinata di trama come descritto nella documentazione di Windows 8.

  • Percorso di output

    float4 d2d_posScene : SCENE_POSITION                
    

    È possibile definire un solo input SCENE_POSITION. Questo parametro deve essere incluso solo quando necessario, poiché una sola funzione per shader collegato può usare questo parametro.

La semantica deve essere definita come precedente, perché D2D esamina la semantica per decidere come collegare le funzioni insieme. Se qualsiasi input di funzione non corrisponde a uno dei tipi precedenti, la funzione verrà rifiutata per il collegamento dello shader.

Helper HLSL

Interfaccia ID3D11Linker

Interfaccia ID3D11FunctionLinkingGraph