Notice
Recent Posts
Recent Comments
Link
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

MOONSUN

[D3D] DirectX 11에서 HLSL 셰이더 컴파일 2가지 방법 본문

D3D

[D3D] DirectX 11에서 HLSL 셰이더 컴파일 2가지 방법

MoonSun_v 2025. 9. 5. 14:23

 

셰이더 ( Shader )

DirectX에서 셰이더는 GPU에서 실행되는 작은 프로그램

  • 버텍스 셰이더(Vertex Shader, VS): 정점 데이터를 받아서 변환
  • 픽셀 셰이더(Pixel Shader, PS): 픽셀 단위로 색상을 계산

 

셰이더는 HLSL 파일(.hlsl)로 작성된다.

하지만 GPU가 바로 HLSL 코드를 이해하지 못하기 때문에 컴파일이 필요하다.

 

 

DirectX 11에서

HLSL(High-Level Shader Language) 셰이더를 컴파일하는 방법은 2가지가 있다.

 

1. 런타임 컴파일 (D3DCompile)

  • 프로그램이 실행될 때 .hlsl 파일을 읽어서 바로 컴파일
  • 장점: 수정 후 바로 테스트 가능
  • 단점: 실행 시 컴파일 오버헤드, 배포 시 HLSL 파일 필요

2. 사전 컴파일 (.cso, Compiled Shader Object)

  • Visual Studio나 fxc.exe로 미리 컴파일해 .cso 파일로 생성
  • 프로그램 실행 시 바로 로드
  • 장점: 빠름, 배포 시 HLSL 파일 필요 없음
  • 단점: HLSL 수정 후 다시 빌드해야 함

 

 

현재 나는 개발 편의성을 위해 런타임에 컴파일하는 방식을 사용하고 있고,

배포용으로는 .cso를 미리 만들어서 사용하는 것이 일반적이라고 한다.

 

 


다음과 같이 런타임 컴파일을 진행하고 있다.

// [ HLSL 셰이더를 파일에서 컴파일 ]
HRESULT CompileShaderFromFile(
    const WCHAR* szFileName,    // 셰이더 파일 이름
    LPCSTR szEntryPoint,        // 진입점 함수 (ex. "main")
    LPCSTR szShaderModel,       // 셰이더 모델 (ex. "ps_5_0")
    ID3DBlob** ppBlobOut        // 결과 셰이더 바이트코드
);


HRESULT CompileShaderFromFile(const WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
	HRESULT hr = S_OK;

	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
	// 디버그 모드일 경우: 디버깅을 쉽게 하기 위해 최적화 끔
	dwShaderFlags |= D3DCOMPILE_DEBUG;
	dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif


	ID3DBlob* pErrorBlob = nullptr;
	hr = D3DCompileFromFile(szFileName, nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, szEntryPoint, szShaderModel,
		dwShaderFlags, 0, ppBlobOut, &pErrorBlob);

	if (FAILED(hr))
	{
		if (pErrorBlob)
		{
			MessageBoxA(NULL, (char*)pErrorBlob->GetBufferPointer(), "CompileShaderFromFile", MB_OK);
			pErrorBlob->Release();
		}
		return hr;
	}
	if (pErrorBlob) pErrorBlob->Release();

	return S_OK;
}

 

// ================================================================
// 버텍스 셰이더(Vertex Shader) 컴파일 및 생성
// ================================================================

ComPtr<ID3DBlob> vertexShaderBuffer; // 컴파일된 버텍스 셰이더 코드(hlsl) 저장 버퍼

// ' HLSL 파일에서 main 함수를 vs_4_0 규격으로 컴파일 '
HR_T(CompileShaderFromFile(L"RectangleVertexShader.hlsl", "main", "vs_4_0", vertexShaderBuffer.GetAddressOf()));

// 버텍스 셰이더 객체 생성
HR_T(m_pDevice->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), nullptr, m_pVertexShader.GetAddressOf()));



// ================================================================
// 픽셀 셰이더(Pixel Shader) 컴파일 및 생성
// ================================================================

ComPtr<ID3DBlob> pixelShaderBuffer; // 컴파일된 버텍스 픽셀 코드(hlsl) 저장 버퍼

// ' HLSL 파일에서 main 함수를 ps_4_0 규격으로 컴파일 '
HR_T(CompileShaderFromFile(L"RectanglePixelShader.hlsl", "main", "ps_4_0", pixelShaderBuffer.GetAddressOf()));

// 픽셀 셰이더 객체 생성
HR_T(m_pDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), nullptr, m_pPixelShader.GetAddressOf()));