DirecX12 | Lecture 8. Root Signature (인프런)
DirectX12 강의 8. Root Signature를 정리한 글입니다.
DirecX12 | Lecture 8. Root Signature (인프런)
강의 정보 🎓
- 강의명: C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈 - Part2: 게임 수학과 DirectX12
- 플랫폼: 인프런
- 현재 섹션: Lecture 8 – Root Signature
- 주요 내용: DirectX 12 Root Descriptor 방식에서 Descriptor Table 기반으로 전환하며, CBV 관리를 위한 구조를 재설계한다.
1. Root Signature 구조 변경
- 기존:
InitAsConstantBufferView()
- 변경:
InitAsDescriptorTable()
1
2
3
std::array<CD3DX12_DESCRIPTOR_RANGE, 1> descriptorRanges = {
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, CBV_REGISTER_COUNT, 0)
};
- 관련 enum 및 상수 정의:
1
2
3
4
enum class CBV_REGISTER_NUMBER {
b0 = 0, b1, b2, b3, b4, END
};
constexpr UINT CBV_REGISTER_COUNT = static_cast<UINT>(CBV_REGISTER_NUMBER::END);
2. ConstantBuffer 리팩토링
- CBV용 리소스를 생성하고 디스크립터 힙에 View를 생성한다.
- 핵심 절차:
D3D12_DESCRIPTOR_HEAP_DESC
설정- 디바이스를 통해 디스크립터 힙 생성
- 시작 주소/인크리먼트 저장
- View를 다수 생성 (예: 256개 슬롯)
CreateView()
→Init()
내부에서 호출
3. TableDescriptorHeap 클래스 도입
- 목적: CBV/SRV/UAV를 테이블 단위로 묶어 관리
- 주요 기능:
Init()
: 디스크립터 힙 생성Clear()
: 그룹 인덱스 초기화SetCBV()
: CPU 핸들을 현재 테이블에 복사CommitTable()
: GPU에 테이블 바인딩
📐 디스크립터 힙 구조 예시:
1
2
3
4
5
6
Shader-visible Descriptor Heap
┌────────────────────────────────────┐
│ Group 0: [CBV0][CBV1][CBV2]... │
│ Group 1: [CBV0][CBV1][CBV2]... │
│ Group 2: [CBV0][CBV1][CBV2]... │
└────────────────────────────────────┘
4. 엔진 구조 반영
Engine
에TableDescriptorHeap
추가한다.CommandQueue::RenderBegin()
에서:Clear()
호출SetDescriptorHeaps()
호출 (프레임당 1회 권장)SetDescriptorHeaps()
은 1개의 CBV/SRV/UAV 힙 + 1개의 Sampler 힙만 바인딩 가능하다.
5. PushData 흐름 변경
PushData()
는 이제D3D12_CPU_DESCRIPTOR_HANDLE
을 반환한다.- 불필요한
SetGraphicsRootConstantBufferView()
를 제거한다.
1
2
3
4
5
6
7
// Mesh.cpp - Render()
D3D12_CPU_DESCRIPTOR_HANDLE handle = constantBuffer->PushData(...);
tableDescriptorHeap->SetCBV(handle, CbvRegisterNumber::b0);
...
tableDescriptorHeap->CommitTable();
이슈 및 트러블슈팅
ConstantBuffer::Init()
에서CreateView()
호출을 누락하였다. → 렌더링 오류 발생- 이후 Render 시점에 CBV 테이블 업데이트 누락에 주의하자.
참고
디스크립터 테이블 전환 이유
항목 설명 Root Descriptor 속도 빠르지만 개수 제한 (최대 64 DWORD) Descriptor Table 확장성과 유연성이 뛰어남 (CBV/SRV/UAV 묶음 사용) 장점 셰이더에 필요한 자원을 테이블로 묶어 GPU에 효율적으로 바인딩 가능 DescriptorHeap 종류
- CBV / SRV / UAV는 같은 힙
- Sampler는 별도 힙
- 한 번에 바인딩 가능한 디스크립터 힙은 최대 2개
요약 및 느낀점 📝
- 루트 시그니처를 디스크립터 테이블 기반으로 개편
- ConstantBuffer는 테이블과 연동 가능한 구조로 재설계되었다.
- GPU에 바인딩할 CBV를 다수 관리할 수 있도록 TableDescriptorHeap 클래스가 작성 되었다.
PushData()
→SetCBV()
→CommitTable()
순서로 렌더링 로직이 수행된다.느낀점 💡 Root Signature와 Descriptor Table내용을 이후 헷갈리지 않고고 잘 사용할 수 있도록 이해하는 것이 매우 중요하다고 느꼈다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.