Freigeben über


Kompilieren eines Effekts (Direct3D 11)

Nachdem ein Effekt erstellt wurde, besteht der nächste Schritt darin, den Code zu kompilieren, um auf Syntaxprobleme zu überprüfen.

Dazu rufen Sie eine der Kompilierungs-APIs auf (D3DX11CompileFromFile, D3DX11CompileFromMemory oder D3DX11CompileFromResource ). Diese APIs rufen den Effektcompiler fxc.exe auf, der HLSL-Code kompiliert. Aus diesem Grund sieht die Syntax für Code in einem Effekt sehr ähnlich wie HLSL-Code aus. (Es gibt einige Ausnahmen, die später behandelt werden.) Der Effektcompiler/hlsl-Compiler, fxc.exe, ist im SDK im Hilfsprogrammordner verfügbar, sodass Shader (oder Effekte) bei Bedarf offline kompiliert werden können. Weitere Informationen finden Sie in der Dokumentation zum Ausführen des Compilers über die Befehlszeile.

Beispiel

Hier sehen Sie ein Beispiel für das Kompilieren einer Effektdatei.

WCHAR str[MAX_PATH];
DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );

hr = D3DX11CompileFromFile( str, NULL, NULL, pFunctionName, pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, NULL, &pBlob, &pErrorBlob, NULL );

Includes

Ein Parameter der Kompilierungs-APIs ist eine Include-Schnittstelle. Generieren Sie eine davon, wenn Sie ein angepasstes Verhalten einschließen möchten, wenn der Compiler eine Includedatei liest. Der Compiler führt dieses benutzerdefinierte Verhalten jedes Mal aus, wenn er einen Effekt erstellt oder kompiliert (der den Includezeiger verwendet). Um angepasstes Includeverhalten zu implementieren, leiten Sie eine Klasse von der ID3DInclude-Schnittstelle ab. Dadurch verfügt Ihre Klasse über zwei Methoden: Open und Close. Implementieren Sie das benutzerdefinierte Verhalten in diesen Methoden.

Suchen nach Einschließen von Dateien

Der Zeiger, den der Compiler im pParentData-Parameter an die Open-Methode Des include-Handlers übergibt, zeigt möglicherweise nicht auf den Container, der die #include Datei enthält, die der Compiler zum Kompilieren des Shadercodes benötigt. Das heißt, der Compiler übergibt möglicherweise NULL in pParentData. Daher wird empfohlen, dass Der Include-Handler eine eigene Liste von Includespeicherorten für Inhalte sucht. Ihr include-Handler kann dynamisch neue Include-Speicherorte hinzufügen, wenn er diese Speicherorte in Aufrufen der Open-Methode empfängt.

Nehmen Sie im folgenden Beispiel an, dass die Includedateien des Shadercodes beide im Verzeichnis somewhereelse gespeichert werden. Wenn der Compiler die Open-Methode des include-Handlers aufruft, um den Inhalt von somewhereelse\foo.h zu öffnen und zu lesen, kann der include-Handler den Speicherort des Verzeichnisses "somewhereelse " speichern. Wenn der Compiler später die Open-Methode des include-Handlers aufruft, um den Inhalt von bar.h zu öffnen und zu lesen, kann der include-Handler automatisch im Verzeichnis somewhereelse nach bar.h suchen.

Main.hlsl:
#include "somewhereelse\foo.h"

Foo.h:
#include "bar.h"

Makros

Bei der Effektkompilierung kann auch ein Zeiger auf Makros erfolgen, die an anderer Stelle definiert sind. Angenommen, Sie möchten den Effekt in BasicHLSL10 ändern, um zwei Makros zu verwenden: null und eins. Der Effektcode, der die beiden Makros verwendet, wird hier gezeigt.

if( bAnimate )
    vAnimatedPos += float4(vNormal, zero) *  
        (sin(g_fTime+5.5)+0.5)*5;
        
    Output.Diffuse.a = one;         

Hier ist die Deklaration für die beiden Makros.

D3D10_SHADER_MACRO Shader_Macros[3] = { "zero", "0", "one", "1.0f", NULL, NULL };

Die Makros sind ein NULL-beendetes Array von Makros. wobei jedes Makro mithilfe einer D3D10_SHADER_MACRO Struktur definiert wird.

Ändern Sie den Aufruf des Kompilierungseffekts, um einen Zeiger auf die Makros zu nehmen.

D3DX11CompileFromFile( str, Shader_Macros, NULL, pFunctionName, 
                       pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, 
                       NULL, &pBlob, &pErrorBlob, NULL );    

HLSL-Shaderflags

Shaderflags geben Shadereinschränkungen für den HLSL-Compiler an. Diese Flags wirken sich auf folgende Weise auf den vom Shadercompiler generierten Code aus:

  • Optimieren Sie die Codegröße.
  • Einschließlich Debuginformationen, die die Flusssteuerung verhindern.
  • Wirkt sich auf das Kompilierziel und darauf aus, ob ein Shader auf Legacyhardware ausgeführt werden kann.

Diese Flags können logisch kombiniert werden, wenn Sie nicht zwei in Konflikt stehende Merkmale angegeben haben. Eine Auflistung der Flags finden Sie unter D3D10_SHADER Konstanten.

FX-Flags

Verwenden Sie diese Flags, wenn Sie einen Effekt erstellen, um entweder kompilierungs- oder Laufzeiteffektverhalten zu definieren. Eine Auflistung der Flags finden Sie unter D3D10_EFFECT Konstanten.

Überprüfen von Fehlern

Wenn während der Kompilierung ein Fehler auftritt, gibt die API eine Schnittstelle zurück, die die Fehler aus dem Effektcompiler enthält. Diese Schnittstelle heißt ID3DBlob. Es ist nicht direkt lesbar; Wenn Sie jedoch einen Zeiger auf den Puffer zurückgeben, der die Daten enthält (bei dem es sich um eine Zeichenfolge handelt), können Sie alle Kompilierungsfehler sehen.

Dieses Beispiel enthält einen Fehler in basicHLSL.fx. Die erste Variablendeklaration tritt zweimal auf.

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

// Declare the same variable twice
float4 g_MaterialAmbientColor;      // Material's ambient color

Dieser Fehler bewirkt, dass der Compiler den folgenden Fehler zurückgibt, wie im folgenden Screenshot des Überwachungsfensters in Microsoft Visual Studio gezeigt.

Screenshot des Visual Studio-watch-Fensters mit einem 0x01997fb8-Fehler

Da der Compiler den Fehler in einem LPVOID-Zeiger zurückgibt, wandeln Sie ihn im Überwachungsfenster in eine Zeichenfolge um.

Hier ist der Code, der den Fehler aus der fehlgeschlagenen Kompilierung zurückgibt.

// Read the D3DX effect file
WCHAR str[MAX_PATH];
ID3DBlob*   l_pBlob_Effect = NULL;
ID3DBlob*   l_pBlob_Errors = NULL;
hr = DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"BasicHLSL10.fx" );
hr = D3DX11CompileFromFile( str, NULL, NULL, pFunctionName, 
                       pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL, 
                       NULL, &pBlob, &pErrorBlob, NULL );      

LPVOID l_pError = NULL;
if( pErrorBlob )
{
    l_pError = pErrorBlob->GetBufferPointer();
    // then cast to a char* to see it in the locals window
}

Rendern eines Effekts (Direct3D 11)