Major Changes: - Created comprehensive DX12 migration plan document - Established DX12 engine module structure - Implemented core infrastructure: * DX12Device: Device initialization, adapter selection, feature detection * DX12CommandQueue: Command queue management with fence synchronization Architecture: - DX12/Core: Fundamental objects (device, command queue) - DX12/Resources: Resource management (planned) - DX12/Rendering: Rendering abstractions (planned) Key Features Implemented: - Automatic adapter selection (chooses best GPU) - Debug layer integration with GPU-based validation - Feature level detection (11_0 to 12_1) - Advanced feature detection (raytracing, mesh shaders, VRS) - Descriptor size caching - Fence-based GPU/CPU synchronization - Command list execution with automatic fence signaling Migration Strategy: - Option A: Gradual transition via DX11 (recommended, 8-10 months) - Option B: Direct DX12 migration (high-risk, 3-4 months) - Option C: Multi-backend architecture (expert-level) Technical Details: - Supports Windows 10 1809+ - Requires DX12 capable GPU (most 2015+ hardware) - Feature Level 11_0 minimum - ComPtr for automatic resource management - Explicit synchronization with fences Documentation: - DX9_TO_DX12_MIGRATION_PLAN.md: 15KB comprehensive guide - Client/Engine/DX12/README.md: Module documentation Status: Phase 1 Complete Next: Command list management, swap chain, resource system Files added: 6 (2 .h, 2 .cpp, 2 .md) Lines of code: ~400 (core infrastructure) This is a foundational commit establishing the DX12 architecture. Full migration will take 3-4 months of development.
694 lines
19 KiB
Markdown
694 lines
19 KiB
Markdown
# DirectX 9 to DirectX 12 Migration Plan
|
|
## RiskYourLife Client - Revolutionary Upgrade
|
|
|
|
---
|
|
|
|
## ⚠️ WARNING: MAJOR ARCHITECTURAL CHANGE
|
|
|
|
DirectX 12는 DirectX 9와 **완전히 다른 아키텍처**입니다. 이는 단순한 API 변환이 아닌 **전면적인 렌더링 엔진 재설계**가 필요합니다.
|
|
|
|
### DX9 vs DX12 핵심 차이점
|
|
|
|
| 측면 | DirectX 9 | DirectX 12 |
|
|
|------|-----------|------------|
|
|
| **추상화 레벨** | High-level (자동화) | Low-level (수동 제어) |
|
|
| **리소스 관리** | 드라이버가 자동 관리 | 개발자가 명시적 관리 |
|
|
| **멀티스레딩** | 제한적 | 완전한 멀티스레드 지원 |
|
|
| **메모리 관리** | 자동 | Descriptor Heaps, 명시적 할당 |
|
|
| **커맨드 제출** | Immediate | Command Lists + Command Queue |
|
|
| **동기화** | 암묵적 | 명시적 Fence 사용 |
|
|
| **파이프라인 스테이트** | 개별 설정 | Pipeline State Objects (PSO) |
|
|
| **셰이더 모델** | SM 3.0 | SM 5.0/5.1/6.0+ |
|
|
| **루트 시그니처** | 없음 | 필수 (리소스 바인딩 정의) |
|
|
|
|
---
|
|
|
|
## 1. 현재 DX9 코드베이스 분석
|
|
|
|
### 1.1 사용 중인 DX9 패턴
|
|
|
|
#### A. 디바이스 생성 및 관리
|
|
```cpp
|
|
// DX9 - BaseGraphicsLayer.cpp
|
|
LPDIRECT3D9 m_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
|
|
m_pD3D->CreateDevice(..., &m_pd3dDevice);
|
|
```
|
|
|
|
#### B. 즉시 렌더링 (Immediate Mode)
|
|
```cpp
|
|
// DX9 - 모든 렌더링 코드
|
|
m_pd3dDevice->SetRenderState(...);
|
|
m_pd3dDevice->SetTexture(0, pTexture);
|
|
m_pd3dDevice->DrawPrimitive(...);
|
|
m_pd3dDevice->Present();
|
|
```
|
|
|
|
#### C. 자동 리소스 관리
|
|
```cpp
|
|
// DX9 - Texture.cpp
|
|
D3DXCreateTextureFromFile(m_pd3dDevice, filename, &pTexture);
|
|
pTexture->Release(); // 간단한 해제
|
|
```
|
|
|
|
#### D. 고정 함수 파이프라인 + 기본 셰이더
|
|
```cpp
|
|
// DX9
|
|
m_pd3dDevice->SetVertexShader(pVS);
|
|
m_pd3dDevice->SetPixelShader(pPS);
|
|
```
|
|
|
|
### 1.2 변환이 필요한 주요 컴포넌트
|
|
|
|
1. **BaseGraphicsLayer** (전면 재작성 필요)
|
|
- 디바이스 생성 로직
|
|
- 스왑체인 관리
|
|
- 커맨드 큐/리스트 시스템
|
|
|
|
2. **리소스 관리 시스템** (새로 구축)
|
|
- Descriptor Heaps
|
|
- 리소스 상태 추적
|
|
- 메모리 할당자
|
|
|
|
3. **렌더링 파이프라인** (재설계)
|
|
- Command List 기반 렌더링
|
|
- PSO (Pipeline State Objects)
|
|
- Root Signature
|
|
|
|
4. **텍스처 시스템** (재작성)
|
|
- 리소스 업로드 큐
|
|
- Subresource 관리
|
|
- Format 변환
|
|
|
|
5. **셰이더 시스템** (업그레이드)
|
|
- HLSL 5.0/6.0
|
|
- Shader Reflection
|
|
- Root Constants
|
|
|
|
---
|
|
|
|
## 2. DX12 아키텍처 설계
|
|
|
|
### 2.1 새로운 클래스 구조
|
|
|
|
```
|
|
DX12GraphicsDevice
|
|
├── DX12CommandQueue (Direct/Compute/Copy)
|
|
├── DX12SwapChain
|
|
├── DX12DescriptorHeapManager
|
|
│ ├── RTV Heap
|
|
│ ├── DSV Heap
|
|
│ ├── CBV_SRV_UAV Heap
|
|
│ └── Sampler Heap
|
|
├── DX12ResourceManager
|
|
│ ├── Upload Buffer Pool
|
|
│ ├── Resource State Tracker
|
|
│ └── Memory Allocator
|
|
├── DX12PipelineStateManager
|
|
│ └── PSO Cache
|
|
└── DX12RootSignatureManager
|
|
└── Root Signature Cache
|
|
|
|
DX12CommandContext (Per-thread)
|
|
├── Command Allocator Pool
|
|
├── Command List
|
|
└── Resource Barrier Batch
|
|
|
|
DX12Fence
|
|
└── GPU/CPU Synchronization
|
|
```
|
|
|
|
### 2.2 렌더링 플로우 재설계
|
|
|
|
```cpp
|
|
// DX12 렌더링 플로우
|
|
Frame Begin:
|
|
1. Wait for previous frame fence
|
|
2. Reset command allocator
|
|
3. Reset command list
|
|
|
|
Record Commands:
|
|
4. Set root signature
|
|
5. Set PSO
|
|
6. Set descriptor heaps
|
|
7. Bind resources via root parameters
|
|
8. Resource barriers (if needed)
|
|
9. Set render targets
|
|
10. Set viewport/scissor
|
|
11. Draw calls
|
|
12. Resource barriers (for present)
|
|
|
|
Submit:
|
|
13. Close command list
|
|
14. Execute on command queue
|
|
15. Signal fence
|
|
16. Present swap chain
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 마이그레이션 전략
|
|
|
|
### 3.1 하이브리드 접근법 (권장)
|
|
|
|
DX12는 너무 복잡하므로, **점진적 전환**을 권장합니다:
|
|
|
|
#### Option A: DX12 래퍼 레이어 구축 (추천)
|
|
```
|
|
기존 DX9 코드
|
|
↓
|
|
DX12 Abstraction Layer (새로 구축)
|
|
↓
|
|
DX12 API
|
|
```
|
|
|
|
**장점**:
|
|
- 기존 코드 로직 유지
|
|
- 단계적 최적화 가능
|
|
- 롤백 용이
|
|
|
|
**단점**:
|
|
- 추가 추상화 레이어 오버헤드
|
|
- DX12의 모든 기능 활용 못할 수 있음
|
|
|
|
#### Option B: 전면 재작성
|
|
모든 렌더링 코드를 DX12 네이티브로 재작성
|
|
|
|
**장점**:
|
|
- 최고 성능
|
|
- DX12 기능 완전 활용
|
|
|
|
**단점**:
|
|
- 개발 시간 매우 김 (3-6개월+)
|
|
- 높은 리스크
|
|
|
|
### 3.2 단계별 마이그레이션 (Option A 기준)
|
|
|
|
#### **Phase 1: DX12 인프라 구축** (2-3주)
|
|
1. ✅ dx12 브랜치 생성
|
|
2. ⏳ DX12 디바이스 및 커맨드 큐 초기화
|
|
3. ⏳ 스왑체인 생성
|
|
4. ⏳ 기본 Descriptor Heap 시스템
|
|
5. ⏳ 커맨드 리스트 관리자
|
|
6. ⏳ 펜스 동기화 시스템
|
|
|
|
#### **Phase 2: 리소스 관리 시스템** (2주)
|
|
7. ⏳ Upload Buffer 관리자
|
|
8. ⏳ 리소스 상태 추적 시스템
|
|
9. ⏳ 텍스처 업로드 시스템
|
|
10. ⏳ 버퍼 관리 (Vertex/Index/Constant)
|
|
|
|
#### **Phase 3: 파이프라인 추상화** (2주)
|
|
11. ⏳ Root Signature 관리
|
|
12. ⏳ PSO 캐싱 시스템
|
|
13. ⏳ 셰이더 컴파일 및 로딩
|
|
14. ⏳ Input Layout 변환
|
|
|
|
#### **Phase 4: 렌더링 래퍼** (3주)
|
|
15. ⏳ DX9-style API 래퍼 구축
|
|
- `SetRenderState()` → PSO 변경
|
|
- `SetTexture()` → Descriptor 바인딩
|
|
- `DrawPrimitive()` → Command List 기록
|
|
16. ⏳ 즉시 모드 에뮬레이션
|
|
17. ⏳ 상태 캐싱 레이어
|
|
|
|
#### **Phase 5: 기존 코드 통합** (2주)
|
|
18. ⏳ BaseGraphicsLayer를 DX12 백엔드로 연결
|
|
19. ⏳ 텍스처 시스템 연동
|
|
20. ⏳ 메시 렌더링 연동
|
|
21. ⏳ UI 렌더링 연동
|
|
|
|
#### **Phase 6: 최적화 및 테스트** (2-3주)
|
|
22. ⏳ 멀티스레드 커맨드 리스트 생성
|
|
23. ⏳ 리소스 스트리밍 최적화
|
|
24. ⏳ GPU 프로파일링
|
|
25. ⏳ 메모리 사용량 최적화
|
|
26. ⏳ 성능 벤치마크
|
|
|
|
**총 예상 기간**: 12-15주 (3-4개월)
|
|
|
|
---
|
|
|
|
## 4. 핵심 코드 변환 예제
|
|
|
|
### 4.1 디바이스 생성
|
|
|
|
```cpp
|
|
// === DX9 (현재) ===
|
|
LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);
|
|
D3DPRESENT_PARAMETERS d3dpp;
|
|
// ... d3dpp 설정 ...
|
|
pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
|
|
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &m_pd3dDevice);
|
|
|
|
// === DX12 (변환 후) ===
|
|
// 1. 디버그 레이어 활성화 (개발용)
|
|
ID3D12Debug* pDebug;
|
|
D3D12GetDebugInterface(IID_PPV_ARGS(&pDebug));
|
|
pDebug->EnableDebugLayer();
|
|
|
|
// 2. Factory 생성
|
|
IDXGIFactory4* pFactory;
|
|
CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(&pFactory));
|
|
|
|
// 3. 어댑터 선택
|
|
IDXGIAdapter1* pAdapter;
|
|
for (UINT i = 0; pFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) {
|
|
DXGI_ADAPTER_DESC1 desc;
|
|
pAdapter->GetDesc1(&desc);
|
|
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) continue;
|
|
|
|
// 4. 디바이스 생성
|
|
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0,
|
|
IID_PPV_ARGS(&m_pDevice)))) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 5. 커맨드 큐 생성
|
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
m_pDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_pCommandQueue));
|
|
|
|
// 6. 스왑체인 생성
|
|
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
|
swapChainDesc.Width = width;
|
|
swapChainDesc.Height = height;
|
|
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
swapChainDesc.SampleDesc.Count = 1;
|
|
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
swapChainDesc.BufferCount = 2; // Double buffering
|
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
|
|
|
IDXGISwapChain1* pSwapChain1;
|
|
pFactory->CreateSwapChainForHwnd(m_pCommandQueue, hWnd,
|
|
&swapChainDesc, nullptr, nullptr, &pSwapChain1);
|
|
pSwapChain1->QueryInterface(IID_PPV_ARGS(&m_pSwapChain));
|
|
```
|
|
|
|
### 4.2 텍스처 로딩
|
|
|
|
```cpp
|
|
// === DX9 (현재) ===
|
|
IDirect3DTexture9* pTexture;
|
|
D3DXCreateTextureFromFile(m_pd3dDevice, L"texture.png", &pTexture);
|
|
m_pd3dDevice->SetTexture(0, pTexture);
|
|
|
|
// === DX12 (변환 후) ===
|
|
// 1. 텍스처 데이터 로드 (CPU)
|
|
int width, height, channels;
|
|
unsigned char* imageData = stbi_load("texture.png", &width, &height, &channels, 4);
|
|
|
|
// 2. 디폴트 힙에 텍스처 리소스 생성
|
|
D3D12_RESOURCE_DESC texDesc = {};
|
|
texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
texDesc.Width = width;
|
|
texDesc.Height = height;
|
|
texDesc.DepthOrArraySize = 1;
|
|
texDesc.MipLevels = 1;
|
|
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
texDesc.SampleDesc.Count = 1;
|
|
texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
|
texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
|
|
|
ID3D12Resource* pTexture;
|
|
m_pDevice->CreateCommittedResource(
|
|
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
|
|
D3D12_HEAP_FLAG_NONE,
|
|
&texDesc,
|
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
|
nullptr,
|
|
IID_PPV_ARGS(&pTexture));
|
|
|
|
// 3. 업로드 버퍼 생성
|
|
UINT64 uploadBufferSize;
|
|
m_pDevice->GetCopyableFootprints(&texDesc, 0, 1, 0, nullptr, nullptr, nullptr, &uploadBufferSize);
|
|
|
|
ID3D12Resource* pUploadBuffer;
|
|
m_pDevice->CreateCommittedResource(
|
|
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
|
|
D3D12_HEAP_FLAG_NONE,
|
|
&CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
|
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
|
nullptr,
|
|
IID_PPV_ARGS(&pUploadBuffer));
|
|
|
|
// 4. 텍스처 데이터를 업로드 버퍼에 복사
|
|
D3D12_SUBRESOURCE_DATA textureData = {};
|
|
textureData.pData = imageData;
|
|
textureData.RowPitch = width * 4;
|
|
textureData.SlicePitch = textureData.RowPitch * height;
|
|
|
|
UpdateSubresources(m_pCommandList, pTexture, pUploadBuffer, 0, 0, 1, &textureData);
|
|
|
|
// 5. 리소스 배리어 (COPY_DEST -> PIXEL_SHADER_RESOURCE)
|
|
D3D12_RESOURCE_BARRIER barrier = {};
|
|
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
barrier.Transition.pResource = pTexture;
|
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
|
m_pCommandList->ResourceBarrier(1, &barrier);
|
|
|
|
// 6. SRV (Shader Resource View) 생성
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
|
srvDesc.Format = texDesc.Format;
|
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
|
srvDesc.Texture2D.MipLevels = 1;
|
|
|
|
m_pDevice->CreateShaderResourceView(pTexture, &srvDesc, descriptorHandle);
|
|
|
|
// 7. 커맨드 리스트 실행 및 업로드 버퍼 대기
|
|
ExecuteCommandList();
|
|
WaitForGPU();
|
|
pUploadBuffer->Release();
|
|
```
|
|
|
|
### 4.3 기본 렌더링
|
|
|
|
```cpp
|
|
// === DX9 (현재) ===
|
|
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0);
|
|
m_pd3dDevice->BeginScene();
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
m_pd3dDevice->SetTexture(0, pTexture);
|
|
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
|
|
m_pd3dDevice->EndScene();
|
|
m_pd3dDevice->Present(NULL, NULL, NULL, NULL);
|
|
|
|
// === DX12 (변환 후) ===
|
|
// 1. 커맨드 할당자 리셋
|
|
m_pCommandAllocator->Reset();
|
|
m_pCommandList->Reset(m_pCommandAllocator, m_pPSO);
|
|
|
|
// 2. Root Signature 및 Descriptor Heap 설정
|
|
m_pCommandList->SetGraphicsRootSignature(m_pRootSignature);
|
|
ID3D12DescriptorHeap* ppHeaps[] = { m_pSrvHeap };
|
|
m_pCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
|
|
|
|
// 3. 백버퍼를 렌더 타겟으로 전환
|
|
D3D12_RESOURCE_BARRIER barrier = {};
|
|
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
barrier.Transition.pResource = m_pRenderTargets[m_frameIndex];
|
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
m_pCommandList->ResourceBarrier(1, &barrier);
|
|
|
|
// 4. 렌더 타겟 설정
|
|
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_pRtvHeap->GetCPUDescriptorHandleForHeapStart(),
|
|
m_frameIndex, m_rtvDescriptorSize);
|
|
m_pCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
|
|
|
|
// 5. 클리어
|
|
const float clearColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
|
m_pCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
|
|
|
// 6. 뷰포트 및 시저 렉트 설정
|
|
m_pCommandList->RSSetViewports(1, &m_viewport);
|
|
m_pCommandList->RSSetScissorRects(1, &m_scissorRect);
|
|
|
|
// 7. 버텍스 버퍼 설정
|
|
m_pCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
m_pCommandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
|
|
|
|
// 8. 텍스처 바인딩 (Root Descriptor Table)
|
|
m_pCommandList->SetGraphicsRootDescriptorTable(0, m_pSrvHeap->GetGPUDescriptorHandleForHeapStart());
|
|
|
|
// 9. 그리기
|
|
m_pCommandList->DrawInstanced(3, 1, 0, 0);
|
|
|
|
// 10. 백버퍼를 Present 상태로 전환
|
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
|
m_pCommandList->ResourceBarrier(1, &barrier);
|
|
|
|
// 11. 커맨드 리스트 닫기 및 실행
|
|
m_pCommandList->Close();
|
|
ID3D12CommandList* ppCommandLists[] = { m_pCommandList };
|
|
m_pCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
|
|
|
|
// 12. Present
|
|
m_pSwapChain->Present(1, 0);
|
|
|
|
// 13. 펜스 신호
|
|
const UINT64 fence = m_fenceValue;
|
|
m_pCommandQueue->Signal(m_pFence, fence);
|
|
m_fenceValue++;
|
|
|
|
// 14. 다음 프레임 인덱스
|
|
m_frameIndex = m_pSwapChain->GetCurrentBackBufferIndex();
|
|
|
|
// 15. 이전 프레임 대기
|
|
if (m_pFence->GetCompletedValue() < fence) {
|
|
m_pFence->SetEventOnCompletion(fence, m_fenceEvent);
|
|
WaitForSingleObject(m_fenceEvent, INFINITE);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 필요한 새로운 파일들
|
|
|
|
### 5.1 DX12 코어 클래스
|
|
|
|
```
|
|
Client/Engine/DX12/
|
|
├── DX12Device.h/cpp
|
|
├── DX12CommandQueue.h/cpp
|
|
├── DX12CommandList.h/cpp
|
|
├── DX12SwapChain.h/cpp
|
|
├── DX12DescriptorHeap.h/cpp
|
|
├── DX12Resource.h/cpp
|
|
├── DX12Fence.h/cpp
|
|
├── DX12PipelineState.h/cpp
|
|
├── DX12RootSignature.h/cpp
|
|
└── DX12Helpers.h (유틸리티 매크로)
|
|
```
|
|
|
|
### 5.2 리소스 관리
|
|
|
|
```
|
|
Client/Engine/DX12/Resources/
|
|
├── DX12ResourceManager.h/cpp
|
|
├── DX12UploadBuffer.h/cpp
|
|
├── DX12Texture.h/cpp
|
|
├── DX12Buffer.h/cpp
|
|
├── DX12MemoryAllocator.h/cpp
|
|
└── DX12ResourceStateTracker.h/cpp
|
|
```
|
|
|
|
### 5.3 렌더링 래퍼
|
|
|
|
```
|
|
Client/Engine/DX12/Rendering/
|
|
├── DX12RenderContext.h/cpp
|
|
├── DX12StateCache.h/cpp
|
|
├── DX12ImmediateContext.h/cpp (DX9 에뮬레이션)
|
|
└── DX12Renderer.h/cpp
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 프로젝트 설정 변경
|
|
|
|
### 6.1 필요 라이브러리
|
|
```
|
|
d3d12.lib
|
|
dxgi.lib
|
|
dxguid.lib
|
|
d3dcompiler.lib // 셰이더 컴파일
|
|
dxcompiler.lib // DXC (선택사항, SM 6.0+)
|
|
```
|
|
|
|
### 6.2 필요 헤더
|
|
```cpp
|
|
#include <d3d12.h>
|
|
#include <dxgi1_6.h>
|
|
#include <d3dcompiler.h>
|
|
#include <DirectXMath.h>
|
|
#include "d3dx12.h" // 헬퍼 헤더 (별도 다운로드)
|
|
```
|
|
|
|
### 6.3 Windows SDK 요구사항
|
|
- **최소**: Windows 10 SDK (10.0.17763.0)
|
|
- **권장**: Windows 11 SDK (최신)
|
|
|
|
---
|
|
|
|
## 7. 리스크 및 도전 과제
|
|
|
|
### 7.1 기술적 도전
|
|
|
|
1. **복잡도 급증**
|
|
- DX9: ~100줄로 기본 렌더링 가능
|
|
- DX12: ~1000줄 필요
|
|
|
|
2. **디버깅 난이도**
|
|
- 잘못된 리소스 상태 → 크래시
|
|
- 동기화 문제 → 간헐적 버그
|
|
- 메모리 누수 추적 어려움
|
|
|
|
3. **성능 최적화**
|
|
- 초기에는 DX9보다 느릴 수 있음
|
|
- 멀티스레딩 활용 필수
|
|
- CPU 오버헤드 관리
|
|
|
|
### 7.2 호환성 문제
|
|
|
|
1. **하드웨어 요구사항**
|
|
- DX12 지원 GPU 필수 (대부분 2015년 이후)
|
|
- Feature Level 11_0 이상
|
|
|
|
2. **OS 요구사항**
|
|
- Windows 10 이상 필수
|
|
- Windows 7/8 지원 불가
|
|
|
|
### 7.3 개발 리소스
|
|
|
|
- **예상 개발 시간**: 3-4개월 (풀타임 1인 기준)
|
|
- **필요 전문성**: DX12, 멀티스레딩, GPU 아키텍처
|
|
- **테스트 부담**: 다양한 GPU 벤더 테스트 필요
|
|
|
|
---
|
|
|
|
## 8. 대안: DX11 고려
|
|
|
|
### 왜 DX11이 더 나을 수 있는가?
|
|
|
|
| 측면 | DX11 | DX12 |
|
|
|------|------|------|
|
|
| **학습 곡선** | 완만 (DX9와 유사) | 매우 가파름 |
|
|
| **개발 시간** | 1-2개월 | 3-4개월 |
|
|
| **성능** | 중상 | 최상 (최적화 시) |
|
|
| **호환성** | Windows 7+ | Windows 10+ |
|
|
| **디버깅** | 쉬움 | 어려움 |
|
|
| **멀티스레딩** | 제한적 | 완전 지원 |
|
|
|
|
**결론**: DX11이 **위험/보상 비율**이 더 좋음
|
|
|
|
---
|
|
|
|
## 9. 권장 접근 방식
|
|
|
|
### Option 1: DX11로 먼저 전환 (추천) ⭐⭐⭐⭐⭐
|
|
```
|
|
DX9 → DX11 (2개월) → 안정화 → DX12 (3개월)
|
|
```
|
|
**이점**:
|
|
- 단계적 학습
|
|
- 중간 마일스톤
|
|
- 위험 분산
|
|
|
|
### Option 2: DX12 직행 (고위험 고수익) ⭐⭐⭐
|
|
```
|
|
DX9 → DX12 (4개월) → 고통 → 고성능
|
|
```
|
|
**이점**:
|
|
- 최신 기술
|
|
- 최고 성능
|
|
- 장기적으로 유리
|
|
|
|
### Option 3: 멀티 백엔드 아키텍처 (전문가용) ⭐⭐⭐⭐
|
|
```
|
|
추상화 레이어
|
|
├── DX9 백엔드 (기존)
|
|
├── DX11 백엔드 (신규)
|
|
└── DX12 백엔드 (신규)
|
|
```
|
|
**이점**:
|
|
- 최대 호환성
|
|
- 점진적 마이그레이션
|
|
- 각 플랫폼 최적화
|
|
|
|
**단점**:
|
|
- 개발 부담 3배
|
|
- 유지보수 복잡
|
|
|
|
---
|
|
|
|
## 10. 실행 계획
|
|
|
|
### 즉시 시작 가능한 작업
|
|
|
|
1. ✅ dx12 브랜치 생성 완료
|
|
2. ⏳ DX12 샘플 프로젝트 생성
|
|
- 최소 삼각형 렌더링
|
|
- 텍스처 매핑
|
|
- 기본 조명
|
|
3. ⏳ 성능 벤치마크 툴 준비
|
|
4. ⏳ DX11 마이그레이션 대안 평가
|
|
|
|
### 다음 결정 포인트
|
|
|
|
**질문**: DX11 경유 vs DX12 직행?
|
|
|
|
**제안**:
|
|
1. DX12 프로토타입 2주 제작
|
|
2. 복잡도 및 성능 평가
|
|
3. DX11 경유 여부 결정
|
|
|
|
---
|
|
|
|
## 11. 리소스 및 참고자료
|
|
|
|
### 학습 자료
|
|
- [DirectX 12 Programming Guide](https://docs.microsoft.com/en-us/windows/win32/direct3d12/directx-12-programming-guide)
|
|
- [Introduction to 3D Game Programming with DirectX 12](https://www.amazon.com/Introduction-3D-Game-Programming-DirectX/dp/1942270062)
|
|
- [DirectX 12 Graphics Samples](https://github.com/microsoft/DirectX-Graphics-Samples)
|
|
|
|
### 헬퍼 라이브러리
|
|
- **d3dx12.h**: 필수 헬퍼 함수
|
|
- **DirectX Tool Kit for DX12**: 유틸리티 라이브러리
|
|
- **DirectX Shader Compiler (DXC)**: 최신 셰이더 컴파일러
|
|
|
|
### 디버깅 도구
|
|
- **PIX for Windows**: GPU 디버거
|
|
- **RenderDoc**: 프레임 캡처
|
|
- **GPU Validation Layer**: 리소스 상태 검증
|
|
|
|
---
|
|
|
|
## 12. 최종 권고사항
|
|
|
|
### 🚨 현실적인 조언
|
|
|
|
**DX9 → DX12는 6개월 이상 걸릴 수 있는 대형 프로젝트입니다.**
|
|
|
|
**추천 경로**:
|
|
```
|
|
Phase 1: DX9 → DX11 (2-3개월)
|
|
↓
|
|
Phase 2: 안정화 및 최적화 (1개월)
|
|
↓
|
|
Phase 3: DX11 → DX12 (3-4개월)
|
|
↓
|
|
Phase 4: DX12 최적화 (2개월)
|
|
```
|
|
|
|
**총 기간**: 8-10개월
|
|
|
|
### 현재 작업 제안
|
|
|
|
1. **DX12 기초 프로토타입 제작** (현재 브랜치)
|
|
- 기본 디바이스 초기화
|
|
- 단순 삼각형 렌더링
|
|
- 복잡도 평가
|
|
|
|
2. **병렬로 DX11 브랜치 생성**
|
|
- DX9 → DX11은 상대적으로 쉬움
|
|
- 2-3주면 작동 가능
|
|
- 즉각적인 성능 향상
|
|
|
|
3. **의사결정**
|
|
- DX11 성공 시 → DX12 장기 프로젝트화
|
|
- DX12 프로토타입 성공 시 → 직행 고려
|
|
|
|
---
|
|
|
|
**작성일**: 2025-12-01
|
|
**작성자**: Claude AI (Anthropic)
|
|
**현재 브랜치**: dx12
|
|
**상태**: 계획 단계 - 실행 대기 중
|
|
|
|
**⚠️ 중요**: 이 문서는 계획서입니다. 실제 구현은 예상보다 복잡할 수 있습니다.
|