Partager via


Compiler un effet (Direct3D 11)

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

Pour ce faire, appelez l’une des API de compilation (D3DX11CompileFromFile, D3DX11CompileFromMemoryou D3DX11CompileFromResource). Ces API appellent le compilateur d’effet fxc.exe, qui compile le code HLSL. C’est pourquoi la syntaxe du code dans un effet ressemble beaucoup au code HLSL. (Il existe quelques exceptions qui seront gérées ultérieurement). Le compilateur d’effet/hlsl, fxc.exe, est disponible dans le kit 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 );

Comprend

Un paramètre 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 : Open et Close. Implémentez le comportement personnalisé dans ces méthodes.

Recherche de fichiers Include

Le pointeur transmis par le compilateur dans le paramètre pParentData à la méthode Opendu 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 de rechercher dans votre gestionnaire include sa propre liste d’emplacements 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 sont tous deux stockés dans le répertoire quelque part. Lorsque le compilateur appelle la méthode Opendu gestionnaire include pour ouvrir et lire le contenu de quelque partelse\foo.h, le gestionnaire include peut enregistrer l’emplacement du quelque part répertoire. Plus tard, lorsque le compilateur appelle la méthode d'Open du gestionnaire include pour ouvrir et lire le contenu de bar.h, le gestionnaire include peut rechercher automatiquement dans le répertoire quelque partelse pour bar.h.

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

Foo.h:
#include "bar.h"

Macros

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

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

Voici la déclaration des deux macros.

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

Les macros sont un tableau de macros se terminant 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 de la manière suivante :

  • 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 conflictuelles. Pour obtenir une liste des indicateurs, consultez D3D10_SHADER constantes.

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 une liste des indicateurs, consultez D3D10_EFFECT Constantes.

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 Espion dans Microsoft Visual Studio.

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

Étant donné que le compilateur retourne l’erreur dans un pointeur LPVOID, convertissez-le 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)