Partager via


Compiler un effet (Direct3D 11)

Une fois qu’un effet a été créé, l’étape suivante consiste à compiler le code pour case activée pour les problèmes de syntaxe.

Pour ce faire, appelez l’une des API de compilation (D3DX11CompileFromFile, D3DX11CompileFromMemory ou D3DX11CompileFromResource ). Ces API appellent le compilateur d’effet fxc.exe, qui compile le code HLSL. C’est pourquoi la syntaxe du code d’un effet ressemble beaucoup au code HLSL. (Il existe quelques exceptions qui seront gérées ultérieurement). Le compilateur d’effets/hlsl, fxc.exe, est disponible dans le sdk dans le dossier utilitaires afin que les nuanceurs (ou effets) puissent être compilés hors connexion si vous le souhaitez. Consultez la documentation relative à l’exécution du compilateur à partir de la ligne de commande.

Exemple

Voici un exemple de compilation d’un fichier d’effet.

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

L’un des paramètres des API de compilation est une interface include. Générez l’un de ces éléments si vous souhaitez inclure un comportement personnalisé lorsque le compilateur lit un fichier include. Le compilateur exécute ce comportement personnalisé chaque fois qu’il crée ou compile un effet (qui utilise le pointeur include). Pour implémenter un comportement d’include personnalisé, dérivez une classe de l’interface ID3DInclude . Cela fournit à votre classe deux méthodes : Ouvrir et Fermer. Implémentez le comportement personnalisé dans ces méthodes.

Recherche de fichiers Include

Le pointeur que le compilateur transmet dans le paramètre pParentData à la méthode Open de votre gestionnaire include peut ne pas pointer vers le conteneur qui inclut le fichier #include dont le compilateur a besoin pour compiler votre code de nuanceur. Autrement dit, le compilateur peut passer null dans pParentData. Par conséquent, nous vous recommandons d’effectuer une recherche dans sa propre liste d’emplacements d’include pour le contenu. Votre gestionnaire include peut ajouter dynamiquement de nouveaux emplacements include, car il reçoit ces emplacements dans les appels à sa méthode Open .

Dans l’exemple suivant, supposons que les fichiers include du code de nuanceur soient tous deux stockés dans le répertoire somewhereelse . Lorsque le compilateur appelle la méthode Open du gestionnaire include pour ouvrir et lire le contenu de somewhereelse\foo.h, le gestionnaire include peut enregistrer l’emplacement du répertoire somewhereelse . Plus tard, lorsque le compilateur appelle la méthode Open du gestionnaire include pour ouvrir et lire le contenu de bar.h, le gestionnaire include peut automatiquement rechercher bar.h dans le répertoire somewhereelse.

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

Foo.h:
#include "bar.h"

Macros

La compilation d’effets peut également prendre un pointeur vers des macros définies ailleurs. Par exemple, supposons que vous souhaitiez modifier l’effet dans BasicHLSL10 pour utiliser deux macros : zéro et une. Le code d’effet qui utilise les deux macros s’affiche ici.

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

Voici la déclaration pour les deux macros.

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

Les macros sont un tableau de macros terminé par NULL ; où chaque macro est définie à l’aide d’un struct D3D10_SHADER_MACRO .

Modifiez l’appel d’effet de compilation pour prendre un pointeur vers les macros.

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

Indicateurs de nuanceur HLSL

Les indicateurs de nuanceur spécifient des contraintes de nuanceur pour le compilateur HLSL. Ces indicateurs affectent le code généré par le compilateur du nuanceur des manières suivantes :

  • Optimisez la taille du code.
  • Y compris les informations de débogage, ce qui empêche le contrôle de flux.
  • Affecte la cible de compilation et indique si un nuanceur peut s’exécuter sur du matériel hérité.

Ces indicateurs peuvent être combinés logiquement si vous n’avez pas spécifié deux caractéristiques en conflit. Pour obtenir la liste des indicateurs, consultez constantes D3D10_SHADER.

Indicateurs FX

Utilisez ces indicateurs lorsque vous créez un effet pour définir le comportement de compilation ou le comportement de l’effet d’exécution. Pour obtenir la liste des indicateurs, consultez constantes D3D10_EFFECT.

Vérification des erreurs

Si, pendant la compilation, une erreur se produit, l’API retourne une interface qui contient les erreurs du compilateur d’effet. Cette interface est appelée ID3DBlob. Il n’est pas directement lisible; Toutefois, en retournant un pointeur vers la mémoire tampon qui contient les données (qui est une chaîne), vous pouvez voir toutes les erreurs de compilation.

Cet exemple contient une erreur dans BasicHLSL.fx. La première déclaration de variable se produit deux fois.

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

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

Cette erreur entraîne le retour de l’erreur suivante par le compilateur, comme illustré dans la capture d’écran suivante de la fenêtre Watch dans Microsoft Visual Studio.

capture d’écran de la fenêtre watch visual studio avec une erreur de 0x01997fb8

Étant donné que le compilateur retourne l’erreur dans un pointeur LPVOID, castez-la en chaîne de caractères dans la fenêtre Espion.

Voici le code qui retourne l’erreur de la compilation ayant échoué.

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

Rendu d’un effet (Direct3D 11)