Udostępnij za pośrednictwem


Łączenie shaderów efektu

Funkcja Direct2D używa optymalizacji nazywanej łączeniem shaderów efektów, która łączy kilkukrotne przejścia renderowania efektów graficznych w jedno.

Omówienie łączenia shaderów efektu

Optymalizacje łączenia shaderów efektu są oparte na łączeniu shaderów HLSL, cesze Direct3D 11.2, która umożliwia generowanie shaderów pikseli i wierzchołków w czasie wykonywania przez powiązanie wstępnie skompilowanych funkcji shaderów. Na poniższych ilustracjach przedstawiono koncepcję łączenia shaderów efektów w wykresie efektowym. Pierwsza ilustracja przedstawia typowy wykres efektu Direct2D z czterema transformacjami renderowania. Bez łączenia shaderów każda transformacja wymaga przejścia renderowania i powierzchni pośredniej; w sumie ten graf wymaga 4 przebiegów i 3 pośrednich.

przekształcanie grafu bez łączenia shaderów: 4 przejścia oraz 3 pośrednie etapy.

Druga ilustracja przedstawia ten sam wykres efektu, w którym każda transformacja renderowania została zastąpiona wersją funkcji z możliwością łączenia. Direct2D jest w stanie połączyć cały graf i wykonać go w jednym przebiegu bez wymagania żadnych pośrednich. Może to zapewnić znaczny spadek czasu wykonywania procesora GPU i zmniejszenie maksymalnego użycia pamięci procesora GPU.

przekształcenie grafu z wiązaniem shaderów: 1 przejście, 0 elementów pośrednich.

 

Łączenie cieniowania efektów działa na poszczególnych przekształceniach w ramach efektu; Oznacza to, że nawet wykres z pojedynczym efektem może korzystać z łączenia cieniowania, jeśli ten efekt ma wiele prawidłowych przekształceń.

Używanie łączenia shaderów efektu

Jeśli tworzysz aplikację Direct2D, która używa efektów, nie musisz podejmować żadnych działań, aby skorzystać z łączenia cieniowania efektów. Funkcja Direct2D automatycznie analizuje wykres efektów, aby określić najbardziej optymalny sposób łączenia każdej transformacji.

Autorzy efektów są odpowiedzialni za zaimplementowanie swoich efektów w sposób, który wspiera łączenie shaderów efektów; aby uzyskać więcej informacji, zobacz sekcję Tworzenie efektu zgodnego z połączeniem shaderów poniżej. Wszystkie wbudowane efekty obsługują łączenie shaderów.

Funkcja Direct2D łączy sąsiadujące przekształcenia renderowania tylko w sytuacjach, gdy jest to korzystne. Uwzględnia wiele czynników podczas określania, czy połączyć dwa przekształcenia. Na przykład łączenie shaderów nie jest wykonywane, jeśli jedna z transformacji używa shaderów wierzchołków lub shaderów obliczeniowych, ponieważ można połączyć tylko shadery pikseli. Ponadto, jeśli efekt nie został utworzony jako zgodny z łączeniem cieniowania, otaczające przekształcenia nie będą z nim powiązane.

W przypadku, gdy takie zagrożenie łączenia istnieje, Direct2D nie będzie łączyć żadnych przekształceń sąsiadujących z zagrożeniem, ale nadal podejmie próbę połączenia pozostałej części grafu.

graf transformacji z zagrożeniem związanym z łączeniem: 2 przebiegi, 1 pośredni krok.

Tworzenie niestandardowego efektu kompatybilnego z łączeniem shaderów

Jeśli tworzysz własny niestandardowy efekt Direct2D, musisz upewnić się, że jego transformacje obsługują łączenie shadera efektu. Wymaga to pewnych drobnych zmian w sposobie implementacji poprzednich efektów niestandardowych. Jeśli transformacja w ramach efektu niestandardowego nie obsługuje łączenia shaderów, funkcja Direct2D nie połączy jej z żadnymi przekształceniami przylegającymi do niej w grafie efektowym.

Jako autor efektów niestandardowych należy pamiętać o kilku kluczowych pojęciach i wymaganiach:

  • Brak zmian w implementacjach interfejsu

    Nie trzeba modyfikować żadnego kodu implementowania różnych interfejsów efektu, takich jak ID2D1DrawTransform.

  • Podaj pełną i eksportową wersję funkcji cieniowania

    Należy podać wersję funkcji eksportu cieniowania efektu, które można połączyć za pomocą funkcji Direct2D. Ponadto należy nadal udostępniać oryginalny, pełny cieniator; Dzieje się tak, ponieważ funkcja Direct2D wybiera w czasie wykonywania odpowiednią wersję cieniowania w zależności od tego, czy łączenie cieniowania ma być stosowane do określonego linku na wykresie.

    Jeśli przekształcenie zapewnia tylko pełny shader piksela (za pośrednictwem ID2D1EffectContext::LoadPixelShader), nie będzie połączone z sąsiednimi przekształceniami.

  • Funkcje pomocnicze

    Direct2D zapewnia funkcje pomocnicze HLSL i makra, które automatycznie generują zarówno pełną, jak i eksportującą wersję funkcji cieniowania. Te pomocniki można znaleźć w d2d1effecthelpers.hlsli. Ponadto, kompilator HLSL (FXC) umożliwia wstawienie shadera funkcji eksportu do pola prywatnego w pełnym shaderze. W ten sposób wystarczy utworzyć cieniowanie tylko raz i przekazać obie wersje do direct2D jednocześnie. Zarówno d2d1effecthelpers.hlsli, jak i kompilator FXC są zawarte w ramach zestawu Windows SDK.

    Funkcje pomocnika:

    Można również ręcznie utworzyć dwie wersje każdego cieniowania i skompilować je dwa razy, o ile specyfikacje opisane poniżej w Eksportuj specyfikacje funkcji są spełnione.

  • Cieniowanie pikseli tylko

    Direct2D nie obsługuje łączenia shaderów obliczeniowych ani wierzchołkowych. Jeśli jednak efekt używa zarówno shaderów wierzchołków, jak i pikseli, wynik działania shadera pikseli wciąż można połączyć.

  • proste i złożone próbkowanie

    Łączenie funkcji cieniowania działa przez połączenie danych wyjściowych cieniowania jednego piksela z wejściem kolejnego przebiegu cieniowania pikseli. Jest to możliwe tylko wtedy, gdy cieniowanie pikseli zużywające wymaga tylko jednej wartości wejściowej do wykonania obliczeń; ta wartość zwykle pochodziłaby z próbkowania tekstury wejściowej na współrzędnych tekstury emitowanych przez cieniowanie wierzchołków. Taki shader pikseli jest znany z wykonywania prostego próbkowania.

    Konwersja skali szarości jest przykładem prostego próbkowania. Wartość określonego piksela wyjściowego zależy tylko od wartości odpowiadającego mu piksela wejściowego.

    Niektóre shadery pikseli, takie jak rozmycie Gaussa, obliczają dane wyjściowe z wielu próbek wejściowych, a nie tylko pojedynczej próbki. Taki shader pikseli wykonuje złożone próbkowanie.

    Gaussian Rozmycie jest przykładem złożonego próbkowania. Wartość środkowego piksela wyjściowego zależy od wielu pikseli wejściowych.

    Tylko funkcje cieniowania z prostymi danymi wejściowymi mogą mieć dane wejściowe udostępniane przez inną funkcję cieniowania. Funkcje cieniowania ze złożonymi danymi wejściowymi muszą być dostarczane z teksturą wejściową do próbkowania. Oznacza to, że Direct2D nie połączy shaderu ze złożonymi danymi wejściowymi ze swoim poprzednikiem.

    W przypadku korzystania z pomocników HLSL Direct2Dnależy wskazać w HLSL, czy cieniator używa złożonych lub prostych danych wejściowych.

Przykładowy shader efektu zgodnego z połączeniem

Korzystając z pomocników D2D, poniższy fragment kodu reprezentuje prosty shader efektu kompatybilny z linkowaniem.

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

W tym krótkim przykładzie zwróć uwagę, że nie zadeklarowano żadnych parametrów funkcji, że liczba danych wejściowych i typ poszczególnych danych wejściowych jest zadeklarowana przed funkcją entry, dane wejściowe są pobierane przez wywołanie D2DGetInputi że dyrektywy preprocesora muszą być zdefiniowane przed dołączenia pliku pomocniczego.

Shader zgodny z łączeniem musi zapewnić zarówno jednoprzepustowy shader pikseli, jak i funkcję eksportu shadera. Makro D2D_PS_ENTRY umożliwia wygenerowanie każdego z nich na podstawie tego samego kodu, gdy jest używane w połączeniu ze skryptem kompilacji cieniowania.

Podczas kompilowania pełnego cieniowania makra są rozszerzane na następujący kod, który ma sygnaturę wejściową zgodną z efektami 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;
    }    

Podczas kompilowania wersji funkcji eksportu tego samego kodu jest generowany następujący kod:

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

Należy pamiętać, że dane wejściowe tekstury, zwykle pobierane przez próbkowanie tekstury2D, zostały zastąpione danymi wejściowymi funkcji (input0).

Aby zapoznać się z pełnym, krok po kroku opisem tworzenia efektu kompatybilnego z łączeniem, zapoznaj się z samouczkiem Efekty niestandardowe oraz przykładem Efekty niestandardowe obrazu Direct2D.

Kompilowanie łączenia zgodnego cieniowania

Aby można było zlinkować, blob shadera pikseli przekazany do D2D musi zawierać zarówno pełne wersje funkcji, jak i eksportowane wersje shadera. Jest to realizowane przez osadzenie skompilowanej funkcji eksportu w obszarze D3D_BLOB_PRIVATE_DATA.

Gdy shadery są tworzone za pomocą funkcji pomocniczych D2D, cel kompilacji D2D musi być zdefiniowany w czasie kompilacji. Typy docelowe kompilacji są D2D_FULL_SHADER i D2D_FUNCTION.

Kompilowanie kompatybilnego z linkowaniem shaderu efektu to proces dwuetapowy:

Notatka

Podczas kompilowania efektu przy użyciu programu Visual Studio należy utworzyć plik wsadowy, który wykonuje polecenia FXC i uruchamia ten plik wsadowy jako niestandardowy krok kompilacji uruchamiany przed krokiem kompilacji.

 

Krok 1. Kompilowanie funkcji eksportu

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

Aby skompilować wersję funkcji eksportu dla twojego shadera, należy przekazać następujące flagi do FXC.

Flaga Opis
/T <ShaderModel> Ustaw <ShaderModel> na odpowiedni profil cieniowania pikseli zgodnie z definicją w FXC Syntax. To musi być jeden z profilów wymienionych w sekcji "Łączenie shaderów HLSL".
<MyShaderFile>.hlsl Ustaw <MyShaderFile> na nazwę pliku HLSL.
/D D2D_FUNCTION Ta definicja instruuje FXC, aby skompilował wersję funkcji eksportu shader.
/D D2D_ENTRY=<wpis> Ustaw wartość <na nazwę> punktu wejściowego HLSL zdefiniowanego wewnątrz makra D2D_PS_ENTRY.
/Fl <MyShaderFile>.fxlib Ustaw <MyShaderfile> w miejscu, gdzie chcesz przechowywać wersję funkcji eksportującej shader. Należy pamiętać, że rozszerzenie fxlib jest tylko w celu ułatwienia identyfikacji.

Krok 2. Kompilowanie pełnego cieniowania i osadzanie funkcji eksportu

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           

Aby skompilować pełną wersję shader z osadzoną wersją eksportu, należy przekazać następujące flagi do FXC.

Flaga Opis
/T <ShaderModel> Ustaw <ShaderModel> na odpowiedni profil cieniowania pikseli zgodnie z definicją w FXC Syntax. Musi to być profil cieniowania pikseli odpowiadający profilowi łączenia określonemu w kroku 1.
<MyShaderFile>.hlsl Ustaw <MyShaderFile> na nazwę pliku HLSL.
/D D2D_FULL_SHADER Ta definicja nakazuje FXC skompilowanie pełnej wersji cieniowania.
/D D2D_ENTRY=<wpis> Ustaw <pozycję> na nazwę punktu startowego HLSL określonego wewnątrz makra D2D_PS_ENTRY().
/E <wejście> Ustaw <elementu> na nazwę punktu wejścia HLSL, który zdefiniowałeś wewnątrz makra D2D_PS_ENTRY().
/setprivate <MyShaderFile>.fxlib Ten argument instruuje FXC, aby osadzić moduł cieniowania funkcji eksportu wygenerowany w kroku 1 w obszarze D3D_BLOB_PRIVATE_DATA.
/Fo <MyShader>.cso Ustaw <MyShader> w miejscu, w którym chcesz przechowywać ostateczny, połączony skompilowany shader.
/Fh <MyShader>.h Ustaw <MyShader> w miejsce, gdzie chcesz przechowywać ostatni, połączony nagłówek.

Eksportowanie specyfikacji funkcji

Istnieje możliwość – choć nie jest to zalecane – aby utworzyć zgodny cieniator efektu bez korzystania z pomocników dostarczonych przez D2D. Należy zachować ostrożność, aby upewnić się, że zarówno pełny shader, jak i sygnatury wejściowe funkcji eksportowania są zgodne ze specyfikacjami D2D.

Specyfikacje dla pełnych shaderów są takie same jak w wcześniejszych wersjach systemu Windows. Krótko mówiąc, parametry wejściowe cieniowania pikseli muszą być takie jak SV_POSITION, SCENE_POSITION i jeden TEXCOORD na dane wejściowe efektu.

W przypadku funkcji eksportu musi ona zwrócić typ danych float4, a jej dane wejściowe muszą być jednym z następujących typów:

  • Proste dane wejściowe

    float4 d2d_inputN : INPUTN         
    

    W przypadku prostych danych wejściowych D2D wstawi funkcję Sample między teksturą wejściową a funkcją cieniowania, albo dane wejściowe będą dostarczane przez dane wyjściowe innej funkcji cieniowania.

  • Złożone dane wejściowe

    float4 d2d_uvN  : TEXCOORDN                
    

    W przypadku złożonych danych wejściowych D2D będzie przekazywać współrzędne tekstury zgodnie z opisem w dokumentacji systemu Windows 8.

  • Lokalizacja wyjściowa

    float4 d2d_posScene : SCENE_POSITION                
    

    Można zdefiniować tylko jedno dane wejściowe SCENE_POSITION. Ten parametr powinien być uwzględniony tylko w razie potrzeby, ponieważ tylko jedna funkcja na połączony moduł cieniowania może korzystać z tego parametru.

Semantyka musi być zdefiniowana jak powyżej, ponieważ D2D sprawdzi semantykę, aby zdecydować, jak połączyć funkcje. Jeśli jakiekolwiek dane wejściowe funkcji nie są zgodne z jednym z powyższych typów, funkcja zostanie odrzucona do łączenia cieniowania.

pomocników HLSL

interfejs ID3D11Linker

interfejs ID3D11FunctionLinkingGraph