Files
Client/DX9_TO_DX12_MIGRATION_PLAN.md
docker-debian b58d615cf2 DX9 to DX12 Migration - Phase 1: Foundation & Planning
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.
2025-12-01 10:23:56 +09:00

19 KiB

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. 디바이스 생성 및 관리

// DX9 - BaseGraphicsLayer.cpp
LPDIRECT3D9 m_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
m_pD3D->CreateDevice(..., &m_pd3dDevice);

B. 즉시 렌더링 (Immediate Mode)

// DX9 - 모든 렌더링 코드
m_pd3dDevice->SetRenderState(...);
m_pd3dDevice->SetTexture(0, pTexture);
m_pd3dDevice->DrawPrimitive(...);
m_pd3dDevice->Present();

C. 자동 리소스 관리

// DX9 - Texture.cpp
D3DXCreateTextureFromFile(m_pd3dDevice, filename, &pTexture);
pTexture->Release(); // 간단한 해제

D. 고정 함수 파이프라인 + 기본 셰이더

// 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 렌더링 플로우 재설계

// 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주)

  1. Upload Buffer 관리자
  2. 리소스 상태 추적 시스템
  3. 텍스처 업로드 시스템
  4. 버퍼 관리 (Vertex/Index/Constant)

Phase 3: 파이프라인 추상화 (2주)

  1. Root Signature 관리
  2. PSO 캐싱 시스템
  3. 셰이더 컴파일 및 로딩
  4. Input Layout 변환

Phase 4: 렌더링 래퍼 (3주)

  1. DX9-style API 래퍼 구축
    • SetRenderState() → PSO 변경
    • SetTexture() → Descriptor 바인딩
    • DrawPrimitive() → Command List 기록
  2. 즉시 모드 에뮬레이션
  3. 상태 캐싱 레이어

Phase 5: 기존 코드 통합 (2주)

  1. BaseGraphicsLayer를 DX12 백엔드로 연결
  2. 텍스처 시스템 연동
  3. 메시 렌더링 연동
  4. UI 렌더링 연동

Phase 6: 최적화 및 테스트 (2-3주)

  1. 멀티스레드 커맨드 리스트 생성
  2. 리소스 스트리밍 최적화
  3. GPU 프로파일링
  4. 메모리 사용량 최적화
  5. 성능 벤치마크

총 예상 기간: 12-15주 (3-4개월)


4. 핵심 코드 변환 예제

4.1 디바이스 생성

// === 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 텍스처 로딩

// === 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 기본 렌더링

// === 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 필요 헤더

#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. 리소스 및 참고자료

학습 자료

헬퍼 라이브러리

  • 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 상태: 계획 단계 - 실행 대기 중

⚠️ 중요: 이 문서는 계획서입니다. 실제 구현은 예상보다 복잡할 수 있습니다.