Łą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.
- Przegląd łączenia shaderów efektów
- linkowanie shaderów efektów
- Tworzenie niestandardowego efektu zgodnego z łączeniem shaderów
- Przykładowy shader efektu zgodny z łączeniem
- Kompilowanie kompatybilnego shadera dla łączenia
- Eksportuj specyfikacje funkcji
- Tematy pokrewne
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.
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.
Łą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.
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:
- D2DGetInput
- D2DSampleInput
- D2DSampleInputAtOffset
- D2DSampleInputAtPosition
- D2DGetInputCoordinate
- D2DGetScenePosition
- D2D_PS_ENTRY
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.
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.
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.
Tematy pokrewne
-
interfejs ID3D11Linker
-
interfejs ID3D11FunctionLinkingGraph