DirectX 12 초기화와 렌더링 시스템 구축

https://youtu.be/P1HEJEIH60A?feature=shared

DirectX 12는 Direct3D 11과 비교하여 근본적으로 다른 설계 철학을 가지고 있습니다. 하드웨어에 더 가까운 저수준 API를 제공함으로써 개발자에게 GPU 리소스와 명령 실행에 대한 명시적인 제어권을 부여합니다. 이를 통해 멀티스레드 렌더링 최적화, 세밀한 메모리 관리, CPU 오버헤드 최소화가 가능해집니다. 초기화 과정은 복잡하지만, 각 구성 요소의 역할과 상호작용을 이해하면 고성능 그래픽 엔진의 기반을 구축할 수 있습니다.


Device: GPU 통신의 핵심 인터페이스

image.png

DirectX 12 디바이스는 GPU와의 모든 상호작용을 관리하는 중앙 허브입니다. 디바이스 생성 과정은 여러 계층의 추상화를 거치며, 각 계층은 특정한 역할을 수행합니다.

순번 계층 역할과 책임
1 응용 프로그램 사용자 코드에서 GraphicDevice_DX12::CreateDevice() 함수를 호출하여 초기화 프로세스를 시작합니다. 이 레벨에서 디바이스 설정, 디버그 옵션, 어댑터 선택 등의 정책을 결정합니다.
2 D3D12 API D3D12CreateDevice() 함수는 표준화된 DirectX 12 인터페이스를 제공합니다. 이 API는 GPU 제조사와 무관하게 일관된 프로그래밍 모델을 제공하며, 리소스 생성, 명령 제출, 동기화 등의 작업을 추상화합니다.
3 사용자 모드 드라이버 GPU 제조사(NVIDIA, AMD, Intel)가 제공하는 드라이버가 DirectX API 호출을 각 GPU의 네이티브 명령어로 변환합니다. 여기서 하드웨어 최적화와 성능 튜닝이 이루어집니다.
4 DXGI DirectX Graphics Infrastructure는 그래픽 하드웨어 관리를 담당합니다. 어댑터 열거, 디스플레이 모드 쿼리, 스왑체인 생성 등 DirectX와 윈도우 시스템 간의 브리지 역할을 수행합니다.
5 커널 모드 드라이버 운영체제 커널 레벨에서 작동하며, 하드웨어 명령을 최종적으로 GPU에 전달합니다. 메모리 보호, 프로세스 격리, 시스템 안정성을 보장하는 역할을 합니다.
6 하드웨어(GPU) 물리적인 그래픽 처리 장치가 명령을 실행하여 실제 렌더링 작업을 수행합니다. 정점 처리, 래스터화, 픽셀 셰이딩, 텍스처 샘플링 등이 여기서 이루어집니다.

DXGI Factory: 하드웨어 탐색과 관리

image.png

if (FAILED(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&mFactory))))
    assert(NULL && "Create DXGI Factory Failed!");

DXGI Factory의 책임

DXGI Factory는 DirectX Graphics Infrastructure의 진입점으로, 시스템의 그래픽 하드웨어와 디스플레이 구성을 파악하는 첫 단계입니다. Factory 객체를 통해 수행할 수 있는 작업들은 다음과 같습니다.

기능 상세 설명
어댑터 열거 EnumAdapters1() 함수로 시스템에 설치된 모든 GPU를 탐색합니다. 각 어댑터의 전용 비디오 메모리, 공유 메모리, PCI ID, 이름 등의 정보를 조회할 수 있습니다. 멀티 GPU 시스템에서는 성능이 가장 높은 어댑터를 선택하거나 특정 용도에 맞는 GPU를 지정할 수 있습니다.
출력 장치 탐색 IDXGIAdapter::EnumOutputs() 함수로 각 GPU에 연결된 모니터를 조회합니다. 멀티 모니터 환경에서 특정 디스플레이를 타겟팅하거나, 디스플레이 간 성능 특성을 고려한 최적화가 가능합니다.
디스플레이 모드 조회 IDXGIOutput::GetDisplayModeList() 함수로 지원 가능한 모든 해상도, 리프레시율, 픽셀 포맷 조합을 확인합니다. 이를 통해 사용자에게 적절한 그래픽 옵션을 제공하고, 최적의 전체화면 모드를 선택할 수 있습니다.
스왑체인 생성 CreateSwapChainForHwnd() 함수로 화면 출력을 위한 백버퍼 관리 객체를 생성합니다. 스왑체인은 더블 버퍼링 또는 트리플 버퍼링을 통해 화면 찢어짐 없는 부드러운 렌더링을 제공합니다.
WARP 어댑터 접근 EnumWarpAdapter() 함수로 CPU 기반 소프트웨어 렌더러에 접근합니다. GPU가 없는 서버 환경이나 원격 데스크톱 세션에서도 DirectX 12 애플리케이션을 실행할 수 있게 합니다.

디버그 레이어 활성화

개발 과정에서 디버그 레이어는 필수적인 도구입니다. API 사용 오류, 리소스 누수, 잘못된 상태 전환, 성능 경고 등을 실시간으로 감지하고 Visual Studio 출력 창에 상세한 정보를 제공합니다.

#if defined(_DEBUG)
    Microsoft::WRL::ComPtr<ID3D12Debug> debugController;
    if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
    {
        debugController->EnableDebugLayer();
        
        // GPU 기반 검증 활성화 (선택적, 성능 저하 큼)
        // debugController->SetEnableGPUBasedValidation(true);
        
        dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
    }
#endif

디버그 레이어는 다음과 같은 오류를 탐지합니다.