효과 컴파일(Direct3D 11)
효과를 작성한 후 다음 단계는 구문 문제에 대한 검사 코드를 컴파일하는 것입니다.
컴파일 API(D3DX11CompileFromFile, D3DX11CompileFromMemory 또는 D3DX11CompileFromResource ) 중 하나를 호출하여 이 작업을 수행합니다. 이러한 API는 HLSL 코드를 컴파일하는 효과 컴파일러 fxc.exe 호출합니다. 이 때문에 효과의 코드 구문은 HLSL 코드와 매우 유사합니다. (나중에 처리될 몇 가지 예외가 있습니다.) 효과 컴파일러/hlsl 컴파일러(fxc.exe)는 유틸리티 폴더의 SDK에서 사용할 수 있으므로 선택한 경우 셰이더(또는 효과)를 오프라인으로 컴파일할 수 있습니다. 명령줄에서 컴파일러를 실행하기 위한 설명서를 참조하세요.
예제
다음은 효과 파일을 컴파일하는 예제입니다.
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
컴파일 API의 매개 변수 중 하나는 포함 인터페이스입니다. 컴파일러가 포함 파일을 읽을 때 사용자 지정된 동작을 포함하려는 경우 이러한 동작 중 하나를 생성합니다. 컴파일러는 포함 포인터를 사용하는 효과를 만들거나 컴파일할 때마다 이 사용자 지정 동작을 실행합니다. 사용자 지정된 포함 동작을 구현하려면 ID3DInclude 인터페이스에서 클래스를 파생합니다. 이렇게 하면 클래스에 Open 및 Close라는 두 가지 메서드가 제공됩니다. 이러한 메서드에서 사용자 지정 동작을 구현합니다.
포함 파일 검색
컴파일러가 pParentData 매개 변수를 포함 처리기의 Open 메서드에 전달하는 포인터는 컴파일러가 셰이더 코드를 컴파일하는 데 필요한 #include 파일을 포함하는 컨테이너를 가리키지 않을 수 있습니다. 즉, 컴파일러는 pParentData에서 NULL을 전달할 수 있습니다. 따라서 포함 처리기는 콘텐츠에 대한 자체 포함 위치 목록을 검색하는 것이 좋습니다. Include 처리기는 Open 메서드에 대한 호출에서 해당 위치를 수신할 때 새 포함 위치를 동적으로 추가할 수 있습니다.
다음 예제에서는 셰이더 코드의 포함 파일이 모두 somewhereelse 디렉터리에 저장되어 있다고 가정합니다. 컴파일러가 include 처리기의 Open 메서드를 호출하여 somewhereelse\foo.h의 내용을 열고 읽을 때 include 처리기는 somewhereelse 디렉터리의 위치를 저장할 수 있습니다. 나중에 컴파일러가 include 처리기의 Open 메서드를 호출하여 bar.h의 내용을 열고 읽을 때 include 처리기는 somewhereelse 디렉터리에서 bar.h를 자동으로 검색할 수 있습니다.
Main.hlsl:
#include "somewhereelse\foo.h"
Foo.h:
#include "bar.h"
매크로
효과 컴파일은 다른 곳에서 정의된 매크로에 대한 포인터를 사용할 수도 있습니다. 예를 들어 BasicHLSL10의 효과를 수정하여 0과 1이라는 두 개의 매크로를 사용한다고 가정합니다. 두 매크로를 사용하는 효과 코드가 여기에 표시됩니다.
if( bAnimate )
vAnimatedPos += float4(vNormal, zero) *
(sin(g_fTime+5.5)+0.5)*5;
Output.Diffuse.a = one;
다음은 두 매크로에 대한 선언입니다.
D3D10_SHADER_MACRO Shader_Macros[3] = { "zero", "0", "one", "1.0f", NULL, NULL };
매크로는 NULL로 끝나는 매크로 배열입니다. 여기서 각 매크로는 D3D10_SHADER_MACRO 구조체를 사용하여 정의됩니다.
매크로에 대한 포인터를 사용하도록 컴파일 효과 호출을 수정합니다.
D3DX11CompileFromFile( str, Shader_Macros, NULL, pFunctionName,
pProfile, D3D10_SHADER_ENABLE_STRICTNESS, NULL,
NULL, &pBlob, &pErrorBlob, NULL );
HLSL 셰이더 플래그
셰이더 플래그는 HLSL 컴파일러에 대한 셰이더 제약 조건을 지정합니다. 이러한 플래그는 다음과 같은 방법으로 셰이더 컴파일러에서 생성된 코드에 영향을 미칩니다.
- 코드 크기를 최적화합니다.
- 흐름 제어를 방지하는 디버그 정보를 포함합니다.
- 컴파일 대상 및 셰이더가 레거시 하드웨어에서 실행할 수 있는지 여부에 영향을 줍니다.
두 가지 충돌하는 특성을 지정하지 않은 경우 이러한 플래그를 논리적으로 결합할 수 있습니다. 플래그 목록은 D3D10_SHADER 상수를 참조하세요.
FX 플래그
컴파일 동작 또는 런타임 효과 동작을 정의하는 효과를 만들 때 이러한 플래그를 사용합니다. 플래그 목록은 D3D10_EFFECT 상수를 참조하세요.
오류 확인
컴파일 중에 오류가 발생하면 API는 효과 컴파일러의 오류가 포함된 인터페이스를 반환합니다. 이 인터페이스를 ID3DBlob이라고 합니다. 직접 읽을 수 없습니다. 그러나 데이터(문자열)가 포함된 버퍼에 대한 포인터를 반환하면 컴파일 오류를 볼 수 있습니다.
이 예제에서는 BasicHLSL.fx에 오류가 있으며 첫 번째 변수 선언은 두 번 발생합니다.
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
// Declare the same variable twice
float4 g_MaterialAmbientColor; // Material's ambient color
이 오류로 인해 컴파일러는 Microsoft Visual Studio에서 조사식 창의 다음 스크린샷과 같이 다음 오류를 반환합니다.
컴파일러는 LPVOID 포인터에서 오류를 반환하므로 조사식 창의 문자열로 캐스팅합니다.
실패한 컴파일에서 오류를 반환하는 코드는 다음과 같습니다.
// 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
}
관련 항목