Direct3D의 초기화

3 minute read

Direct3D의 초기화

COM(Component Object Model)

DirectX의 프로그래밍 언어 독립성과 하위 호환성을 가능하게 하는 기술

직접 생성할 일 없고 COM 인터페이스를 가리키는 포인터를 얻어서 사용한다.

사용 후에는 Relaeas 메서드를 호출하여 해제해야한다.

COM 객체는 참조 횟수가 0이 되면 메모리에서 해제된다.

WRL::ComPtr, 스마트 포인터

범위를 벗어난 ComPtr 인스턴스는 자동으로 Release를 호출한다.

Get, GetAddressOf, Reset 함수만을 사용해도 충분

COM 인터페이스들은 이름이 대문자 I(i)로 시작한다.

텍스처 형식

교환사슬

전면버퍼, 후면버퍼

제시(presenting): 전면 버퍼와 후면버퍼의 역할을 교환해서 페이지가 전환되게 하는 것

전환 시에는 포인터만 맞바꾸면 된다.

IDXGISwapChain: 교환 사슬을 대표하는 인터페이스

깊이 버퍼링, z-버퍼링

깊이 정보를 담은 깊이 버퍼를 이용하여 그리는 순서와 무관하게 가리는 물체를 판정하여 그릴수 있다.

자원

렌더링 파이프 라인에 자원을 바인딩하여 렌더링을 한다.

실제로 바인딩 되는것은 자원을 참조하는 서술자이다.(범용적으로 사용하기 위해)

GPU는 자원의 형식을 알 수 없다.

서술자

자원을 GPU에 서술하는 수단

서술자를 이용하여 자원의 형식을 명시할 수 있다.

CBV/SRV/UAV 서술자들은 상수버퍼, 셰이더 자원, 순서 없는 접근을 서술

표본추출기 서술자는 텍스처 적용에 쓰이는 표본추출기 자원을 서술

RTV 서술자는 렌더 대상 자원을 서술

DSV 서술자는 깊이/스텐실 자원을 서술

서술자 힙(descriptor heap)

다중표본화

안티앨리어싱

초과표본화: 버퍼를 화면 해상도보다 4배 크게 잡고 렌더링 화면에 출력할때는 원래 크기로 환원하여 사용, 하향 표본화라고도 함

다중표본화는 부분픽셀을 이용, 4배 크게 하는건 같지만 픽셀의 중심에서 계산하여 최종 색상 결정

ID3D12Device::CheckFeatureSupport를 이용하여 텍스처 형식과 표본 개수의 조합에 대한 품질 수준들의 개수를 알수 있다.

기능수준

DXGI(DirectX Graphics Infrastructure)

전체 화며 모드전환, 디스플레이 어댑터나 모니터, 지원되는 디스플레이 모드 같은 그래픽 시스템정보의 열거 등의 기능 제공

IDXGIFactory 인터페이스: IDXGISwapChain 인터페이스 생성, 디스플레이 어댑터 열거에 사용

상주성

CPU명령 목록, GPU 명령대기열

명령 대기열이 비면 GPU는 할일이 없고, 대기열이 꽉 차면 GPU가 명령들을 처리하여 대기열에 자리가 생길 때까지 CPU가 놀게 된다.

명령 대기열을 대표하는 인터페이스 ID3D12CommandQueue

ID3D12CommandQueue::ExecuteCommandLists 명령 목록에 있는 명령을 대기열에 추가하는 메서드

ID3D12GraphicsCommandList::Close 명령 목록 닫기 메서드, 명령 목록을 제출하기 전에 먼저 닫아줘야 함

ID3D12Device::CreateCommandAllocator 명령 메모리 할당자 생성 메서드

ID3D12Device::CreateCommandList 명령 목록 생성 메서드

명령들을 여러 명령 목록에 동시에 기록할 수는 없으며 현재 명령들을 추가하는 명령 목록을 제외한 모든 명령 목록은 닫혀있어야한다.

GPU가 명령 할당자에 담긴 모든 명령을 실행했음이 확실해지기 전까지는 명령 할당자를 재설정하면 안된다.

CPU/GPU 동기화

자원 상태 전이

자원에 상태를 부여하여 자원 위험 상황을 해결

자원 위험 상황: GPU가 자원에 자료를 다 기록하지 않았거나 기록을 시작하지 않은 상태에서 자원의 자료를 읽으려하는 문제

Direct3D 초기화 과정

  1. D3D12CreateDevice 함수를 이용해서 ID3D12Device를 생성
  2. ID3D12Fence 객체를 생성하고 서술자들의 크기를 얻는다.
  3. 4X MSAA 품질 수준 지원 여부를 점검
  4. 명령 대기열과 명령 목록 할당자, 그리고 주 명령 목록을 생성
  5. 교환 사슬을 서술하고 생성
  6. 응용 프로그램에 필요한 서술자 힙들을 생성
  7. 후면 버퍼의 크기를 설정하고, 후면 버퍼에 대한 렌더 대상 뷰를 생성
  8. 깊이/스텔실 버퍼를 생성하고, 그와 연관된 깊이/스텐실 뷰를 생성
  9. 뷰포트와 가위 판정용 사각형들을 설정

장치 생성

Direct3D 초기화는 Direct3D 12 장치(ID3D12Device)를 생성하는 것으로 시작한다.

장치는 디스플레이 어댑터를 나타내는 객체이다.

디스플레이 어댑터는 그래픽 카드, 소프트웨어 디스플레이 어댑터(WARP 어댑터) 등을 의미한다.

4X MSAA 품질 수준 지원 점검

Direct3D 11 이상이면 지원 여부 확인 필요 없다.

책에서는 예제 코드를 보여준다.

명령 대기열과 명령 목록 생성

D3DAPP::CreateCommandObjects 메소드를 이용하여 생성

교환 사슬의 서술과 생성

DXGI_SWAP_CHAIN_DESC, DXGI_MODE_DESC 구조체 인스턴스의 멤버들을 지금 생성하고자 하는 교환 사슬에 맞게 설정해야 한다.

IDXGIFactory::CreateSwapChain 메소드를 이용하여 교환사슬 생성

서술자(뷰) 힙 생성

ID3D12Device::CreateDescriptorHeap 메소드를 이용하여 생성

SwapChainBufferCount에 설정된 개수만큼 RTV, DSV이 필요하며 서술자 힙은 서술자 종류마다 따로 만들어야 한다.(RTV를 담는 힙, DSV를 담는 힙)

렌더 대상 뷰(RTV) 생성

후면 버퍼에 렌더링 하기 위해 후면 버퍼를 파이프라인의 출력 병합기 단게에 묶는다. 이를 위해 후면 버퍼에 대한 렌더 대상 뷰를 생성한다.

IDXGISwapChain::GetBuffer 메소드를 이용하여 버퍼를 얻는다.

이 메소드를 호출하면 후면 버퍼의 COM 참조 횟수가 증가한다.(다 쓴후에는 해제 해야함, ComPtr을 사용하면 자동 처리)

ID3D12Device::CreateRenderTargetView 메소드를 이용하여 렌더 대상 뷰 생성

깊이 스텐실 버퍼와 뷰 생성

D3D12_RESOURCE_DESC 구조체를 채운후 ID3D12Device::CreateCommittedResources를 호출하여 깊이 스텐실 버퍼 생성

깊이 스텐실 버퍼를 사용하기 전에 반드시 그와 연관된 깊이 스텐실 뷰를 생성해서 파이프라인에 묶어야한다.

뷰포트 설정

3차원 장면을 후면 버퍼의 일부를 차지하는 직사각형 영역에만 그리는 것도 가능한데, 이를 뷰포트라고 부른다.

D3D12_VIEWPORT 구조체를 이용하여 뷰포트를 서술한다.

ID3D12CommandList::RSSetViewports 메서드를 이용해서 뷰포트를 Direct3D에 설정

가위 직사각형

가위 직사각형은 특정 픽셀들을 선별하는 용도로 쓰인다. 특정 영역(UI 등등)을 가리는 요소가 있다면 그 부분의 픽셀을 처리 하지 않을때 사용

D3D12_RECT 구조체로 서술한다.

ID3D12CommandList::RSSetScissorRects 메서드를 이용하여 설정

시간 측정과 애니메이션

정확한 애니메이션 수행을 위해 시간을 측정한다.

두 프레임 사이에 흐른 시간의 양을 측정한다.

성능 타이머

Windows가 제공하는 성능타이머를 사용하며 QueryPerformanceCounter 함수를 사용

이 함수를 사용하면 초당 틱 수를 알 수 있다.

GameTimer클래스

성능타이머의 주파수를 조회해서 틱당 초 수 를 설정하는 등의 작업을 하는 클래스 예제

전체 시간

전체 시간 - 일시정지 시간 = 유효한 전체 시간