다음을 통해 공유


효과 컴파일(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 인터페이스에서 클래스를 파생합니다. 이렇게 하면 클래스에 OpenClose라는 두 가지 메서드가 제공됩니다. 이러한 메서드에서 사용자 지정 동작을 구현합니다.

포함 파일 검색

컴파일러가 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에서 조사식 창의 다음 스크린샷과 같이 다음 오류를 반환합니다.

0x01997fb8 오류가 있는 visual studio watch 창의 스크린샷

컴파일러는 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
}

효과 렌더링(Direct3D 11)