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 prüfen.

Dazu rufen Sie eine der Kompilierungs-APIs auf (D3DX11CompileFromFile, D3DX11CompileFromMemoryoder D3DX11CompileFromResource ). Diese APIs rufen den Effektcompiler fxc.exeauf, 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) offline kompiliert werden können, wenn Sie dies auswählen. Informationen zum Ausführen des Compilers über die Befehlszeile finden Sie in der Dokumentation.

Beispiel

Hier ist ein Beispiel zum 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 );

Enthält

Ein Parameter der Kompilierungs-APIs ist eine include-Schnittstelle. Generieren Sie eines dieser Elemente, 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 erhalten Sie 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 Includehandlers übergibt, verweist 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 ihr Includehandler eine eigene Liste von Aufnahmespeicherorten für Inhalte durchsucht. Der include-Handler kann dynamisch neue Includespeicherorte hinzufügen, da er diese Speicherorte in Aufrufen der Open-Methode empfängt.

Gehen Sie im folgenden Beispiel davon aus, dass die Includedateien des Shadercodes in der irgendwo Verzeichnis gespeichert sind. Wenn der Compiler die Open-Methode des Includehandlers aufruft, um den Inhalt von somewhereelse\foo.hzu öffnen und zu lesen, kann der include-Handler den Speicherort des irgendwo Verzeichnis speichern. Wenn der Compiler die Open-Methode des Includehandlers aufruft, um den Inhalt von bar.hzu öffnen und zu lesen, kann der include-Handler automatisch im Verzeichnis für bar.hsuchen.

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

Foo.h:
#include "bar.h"

Macros

Die Effektkompilierung kann auch einen Zeiger auf Makros ausführen, 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;         

Dies ist die Deklaration für die beiden Makros.

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

Bei den Makros handelt es sich um 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 setzen.

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

HLSL-Shaderkennzeichnungen

Shaderkennzeichnungen geben Shadereinschränkungen für den HLSL-Compiler an. Diese Flags wirken sich auf den vom Shadercompiler generierten Code folgendermaßen aus:

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

Diese Flags können logisch kombiniert werden, wenn Sie nicht zwei widersprüchliche 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 das Kompilierungsverhalten oder das 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 des Effektcompilers enthält. Diese Schnittstelle wird ID3DBlobgenannt. Es ist nicht direkt lesbar; Wenn Sie jedoch einen Zeiger auf den Puffer zurückgeben, der die Daten enthält (eine Zeichenfolge), 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-Überwachungsfensters mit einem 0x01997fb8 Fehler

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

Nachfolgend sehen Sie den 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)