Quick Reference
entry point: VSMain, PSMain처럼 실행을 시작할 함수
profile: vs_5_0, ps_5_0처럼 stage와 shader model 지정
flags: Debug/SkipOptimization 또는 release optimization 선택
bytecode: Create*Shader와 CreateInputLayout에 전달
error blob: 실패 원문을 즉시 logEntry point와 profile stage가 맞지 않으면 컴파일 또는 shader 생성이 실패합니다. Runtime 경로보다 build 단계에서 shader를 컴파일해 배포 누락을 줄일 수 있습니다.
컴파일
const wchar_t* path = L"shaders/basic.hlsl";
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined(_DEBUG)
flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
ComPtr<ID3DBlob> bytecode;
ComPtr<ID3DBlob> errors;
HRESULT hr = D3DCompileFromFile(path, nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
"VSMain", "vs_5_0", flags, 0, bytecode.GetAddressOf(), errors.GetAddressOf());
if (FAILED(hr)) {
if (errors) {
OutputDebugStringA(static_cast<const char*>(errors->GetBufferPointer()));
}
throw std::runtime_error("HLSL compilation failed");
}FAILED(hr)를 먼저 확인하고 error blob이 있을 때만 메시지를 읽습니다. 컴파일 실패가 항상 error blob을 돌려준다고 보장할 수 없으며, 실패한 bytecode도 사용하면 안 됩니다. Include root, macro 조합과 working directory를 암묵적으로 두면 IDE와 배포 실행 환경에서 결과가 달라질 수 있으므로 asset root를 하나로 고정합니다.
Bytecode 사용
VS bytecode는 CreateVertexShader뿐 아니라 input layout 검증에도 사용됩니다. Shader COM 객체가 만들어진 뒤 compile blob은 보통 해제할 수 있지만 input layout 생성 전에는 유지해야 합니다. Cache key에는 파일 내용, macro, entry point, profile과 compiler option을 포함합니다.
자주 틀리는 점
- Debug compiler flag를 release 성능 측정에 그대로 쓰지 않습니다.
- 파일 timestamp 하나만 cache key로 믿지 않습니다.
- Pixel shader bytecode로 input layout을 만들지 않습니다.
- Compiler DLL과 shader asset 배포 누락을 실행 환경에서 확인합니다.
참고 링크
2 sources