Compilar un efecto (Direct3D 11)
Una vez creado un efecto, el siguiente paso consiste en compilar el código para comprobar si hay problemas de sintaxis.
Para ello, llame a una de las API de compilación (D3DX11CompileFromFile, D3DX11CompileFromMemory o D3DX11CompileFromResource ). Estas API invocan al compilador de efectos fxc.exe, que compila código HLSL. Este es el motivo por el que la sintaxis del código en un efecto es muy similar al código HLSL. (Hay algunas excepciones que se controlarán más adelante). El compilador de efectos/compilador hlsl, fxc.exe, está disponible en el SDK en la carpeta utilidades para que los sombreadores (o efectos) se puedan compilar sin conexión si lo decide. Consulte la documentación para ejecutar el compilador desde la línea de comandos.
- Ejemplo
- Incluye
- Buscar archivos de inclusión
- Macros
- Marcas de sombreador HLSL
- Marcas FX
- Comprobación de errores
- Temas relacionados
Ejemplo
Este es un ejemplo de compilación de un archivo de efecto.
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
Un parámetro de las API de compilación es una interfaz include. Genere uno de estos si desea incluir un comportamiento personalizado cuando el compilador lee un archivo de inclusión. El compilador ejecuta este comportamiento personalizado cada vez que crea o compila un efecto (que usa el puntero de inclusión). Para implementar el comportamiento de inclusión personalizado, derive una clase de la interfaz ID3DInclude . Esto proporciona a la clase dos métodos: Open y Close. Implemente el comportamiento personalizado en estos métodos.
Buscar archivos de inclusión
Es posible que el puntero que el compilador pase en el parámetro pParentData al método Open del controlador de inclusión no apunte al contenedor que incluye el archivo #include que el compilador necesita para compilar el código del sombreador. Es decir, el compilador puede pasar NULL en pParentData. Por lo tanto, se recomienda que el controlador de inclusión busque su propia lista de ubicaciones de inclusión para el contenido. El controlador de inclusión puede agregar dinámicamente nuevas ubicaciones de inclusión a medida que recibe esas ubicaciones en llamadas a su método Open .
En el ejemplo siguiente, supongamos que los archivos de inclusión del código del sombreador se almacenan en el directorio somewhereelse . Cuando el compilador llama al método Open del controlador de inclusión para abrir y leer el contenido de somewhereelse\foo.h, el controlador de inclusión puede guardar la ubicación del directorio somewhereelse . Más adelante, cuando el compilador llama al método Open del controlador de inclusión para abrir y leer el contenido de bar.h, el controlador de inclusión puede buscar automáticamente en el directorio somewhereelse para bar.h.
Main.hlsl:
#include "somewhereelse\foo.h"
Foo.h:
#include "bar.h"
Macros
La compilación de efectos también puede tomar un puntero a las macros que se definen en otro lugar. Por ejemplo, supongamos que desea modificar el efecto en BasicHLSL10, para usar dos macros: cero y una. Aquí se muestra el código de efecto que usa las dos macros.
if( bAnimate )
vAnimatedPos += float4(vNormal, zero) *
(sin(g_fTime+5.5)+0.5)*5;
Output.Diffuse.a = one;
Esta es la declaración de las dos macros.
D3D10_SHADER_MACRO Shader_Macros[3] = { "zero", "0", "one", "1.0f", NULL, NULL };
Las macros son una matriz terminada en NULL de macros; donde cada macro se define mediante un D3D10_SHADER_MACRO struct.
Modifique la llamada de efecto de compilación para tomar un puntero a las macros.
D3DX11CompileFromFile( str, Shader_Macros, NULL, pFunctionName,
pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL,
NULL, &pBlob, &pErrorBlob, NULL );
Marcas de sombreador HLSL
Las marcas de sombreador especifican restricciones de sombreador para el compilador HLSL. Estas marcas afectan al código generado por el compilador de sombreador de las siguientes maneras:
- Optimice el tamaño del código.
- Incluir información de depuración, que impide el control de flujo.
- Afecta al destino de compilación y si un sombreador se puede ejecutar en hardware heredado.
Estas marcas se pueden combinar lógicamente si no se han especificado dos características en conflicto. Para obtener una lista de las marcas, consulte D3D10_SHADER Constantes.
Marcas FX
Use estas marcas al crear un efecto para definir el comportamiento de compilación o el comportamiento del efecto en tiempo de ejecución. Para obtener una lista de las marcas, consulte D3D10_EFFECT Constantes.
Comprobación de errores
Si durante la compilación se produce un error, la API devuelve una interfaz que contiene los errores del compilador de efectos. Esta interfaz se denomina ID3DBlob. No es legible directamente; sin embargo, al devolver un puntero al búfer que contiene los datos (que es una cadena), puede ver los errores de compilación.
Este ejemplo contiene un error en BasicHLSL.fx, la primera declaración de variable se produce dos veces.
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
// Declare the same variable twice
float4 g_MaterialAmbientColor; // Material's ambient color
Este error hace que el compilador devuelva el siguiente error, como se muestra en la siguiente captura de pantalla de la ventana Inspección de Microsoft Visual Studio.
Dado que el compilador devuelve el error en un puntero LPVOID, consértalo a una cadena de caracteres en la ventana Inspección.
Este es el código que devuelve el error de la compilación con errores.
// 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
}
Temas relacionados