Direct3D는 응용 프로그램에서 GPU를 제어하고 프로그래밍 하는데 쓰이는 저수준 그래픽 API이다.

 

Direct3D12는 Direct3D11보다 훨씬 낮은 수준의 API가 되었다.

다중 스레드 지원을 개선하기 위해 이전보다 추상화가 줄었고, 개발자가 손수 관리해야할 사항들이 늘어났다.

4.1.2 COM 객체 (Component Object Model)

COM 객체 전용 스마트포인터 ComPtr 클래스를 사용하여 관리

 

COM 인터페이스를 가리키는 포인터는 new 키워드로 직접 생성하지 않고 보통 특별한 함수를 호출해서 얻는다. (Comptr와 desc 구조체를 넘겨 COM 객체를 초기화한다)

 

COM 인터페이스를 다 사용하고 난 후에는 delete로 삭제하는 것이 아니라 그 인터페이스의 Release 메서드를 호출한다.

Release 메서드는 Shared_ptr처럼 COM 객체의 참조 횟수가 0이 될 때 호출되어 메모리에서 해제시킨다.

ComPtr은 범위 밖을 벗어나면 자동으로 COM에 대해 Release 함수를 호출하므로 사용자가 Release를 호출할 필요가 없다.

 

ComPtr<[Com 인터페이스]> [변수이름] 

ComPtr 클래스의 함수

1. Get : ComPtr이 가리키는 Com 인터페이스를 반환

2. GetAddressOf : Comptr이 가리키는 Com 인터페이스의 주소를 반환

3. Reset : ComPtr 인스턴스를 nullptr로 설정하고 Com 인터페이스의 참조 횟수를 1 감소

 

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

 

4.1.3 텍스처 형식

1. RGBA 색상 원소를 담을 수 있다.

DXGI_FORMAT_R8G8B8A8_UINT

2. 부동 소수점 원소를 담을 수 있다.

DXGI_FORMAT_R32G32B32_FLOAT

3. 무형식 텍스쳐 형식

DXGI_R16G16B16A16_TYPELESS

 

4.1.4 교환 사슬과 페이지 전환

전면 버퍼와 후면 버퍼는 하나의 교환 사슬을 형성한다.

교환 사슬을 대표하는 인터페이스는 IDXGISwapChain이다. 이 인터페이스는 전면 버퍼 텍스처와 후면 버퍼 텍스처를 담는다. 화면에 현재 프레임에 전면 버퍼가 표시될 동안 후면 버퍼에 다음 프레임을 렌더링하고 다음 프레임에 버퍼를 교환하는 방법

이중 버퍼링 : 전면과 후면으로 버퍼를 두개 사용하는 방법

 

4.1.5 깊이 버퍼링

전면 후면 버퍼와 동일한 해상도를 가지는 버퍼

깊이 값은 [0, 1] 사이 값을 가짐

 

깊이 버퍼링을 위한 텍스처 형식

1. DXGI_FORMAT_D32_FLOAT_S8X24_UINT

ㄴ 32비트 부동소수점 깊이, 8비트 스텐실[0, 255], 24 패딩

2. DXGI_FORMAT_D32_FLOAT

ㄴ 32비트 부동소수점 깊이

3. DXGI_FORMAT_D24_UNORM_S8_UINT

ㄴ 24비트 부호없는 깊이[0, 1], 8비트 스텐실[0, 255]

4. DXGI_FORMAT_D16_UNORM

ㄴ 16비트 부호없는 깊이[0, 1]

 

4.1.6 자원과 서술자

자원 : 버퍼, 텍스처

 

렌더링 파이프라인에서 그리기 호출마다 해당 그리기 호출이 참조할 자원을 묶어줘야 한다.

자원을 묶는 대신에 자원을 설명하는 서술자를 파이프라인에 묶는다.

 

같은 자원을 렌더링 파이프라인의 서로 다른 단계에서 사용할 수 있기 때문에 이런 방식을 쓴다.

 

같은 자원이더라도 여러 방법으로 사용될 수 있다.

렌더 대상

깊이 스텐실 버퍼

셰이더 자원

 

무형식으로 생성된 자원은 해당 자원의 서술자 만들때 형식을 명시할 수 있다.

형식이 완전히 지정된 자원은 런타임에서 자원 접근을 최적화할 수 있게 되기 때문에, 필요한 경우에만 무형식으로 자원을 만들어야 한다.

 

서술자는 자원 자료를 지정하는 수단일 뿐만 아니라, 자원을 GPU에 서술하는 수단이기도 하다.

서술자의 종류

1. CRV/SRV/UAV 서술자 : 상수버퍼 / 셰이더 자원 / 순서 없는 접근

2. 표본추출기 서술자 : sampler 자원을 서술

3. RTV 서술자 : 렌더 대상 자원을 서술

4. DSV : 깊이스텐싈 자원을 서술

 

서술자는 프로그램 초기화 시점에서 형식 점검과 유효성 검증이 일어나기 때문에 초기화 시점에 서술자를 생성해야 한다.

 

서술자 힙

ㄴ 서술자들의 배열

서술자의 종류마다 서술자 힙이 필요하다.

4.1.7 다중표본화

초과 표본화 : 화면 해상도보다 4배 큰 후면 버퍼에 렌더링 후 4픽셀의 평균 색상을 최종 색상으로 사용

 

다중 표본화 : 4X 다중표본화(픽셀당 부분픽셀 4개)의 경우 화면 해상도보다 4배 큰 후면버퍼에 렌더링

픽셀당 색상을 한번 계산

그 픽셀이 보이는 부분픽셀에 복제됨(부분픽셀 마다 깊이 스텐실 판정)

4개의 부분픽셀의 색상을 평균낸 것이 결과 픽셀이 됨

4.1.8 Direct3D의 다중표본화

DXGI_SAMPLE_DESC라는 구조체 인스턴스를 채워야 한다.

Count : 픽셀당 추출할 부분픽셀의 개수

Quality : 품질 수준 (하드웨어마다 다름)

 

Direct3D 12 장치는 4X 다중표본화를 지원한다.

 

4.1.9 기능 수준

기능 수준 12를 지원하는 GPU는 반드시 Direct3D 12의 기능 집합 전체를 지원해야 한다.

4.1.10 DXGI

DXGI API가 제공하는 것들

1. 교환사슬

2. 전체화면 모드 전환

3. 디스플레이 어댑터, 모니터, 지원되는 디스플레이 모드 같은 그래픽 시스템 정보의 열거

 

IDXGIFactory 인터페이스

ㄴ IDXGISwapChain 인터페이스 생성

ㄴ 디스플레이 어댑터 열거

어댑터 하나에는 모니터가 여러개 연결될 수 있다. (IDXGIOuput)

모니터 하나에는 여러개의 디스플레이 모드가 있다. (DXGI_MODE_DESC)

ㄴ 해상도 (너비 높이)

ㄴ 디스플레이 형식

4.1.11 기능 지원 점검

CheckFeatureSupport 메서드로 점검 할 수 있는 기능

ㄴ 기능 수준

ㄴ 주어진 텍스처 형식에 대한 기능들 ( 해당 형식을 렌더 대상으로 사용할 수 있는가, 혼합을 적용할 수 있는가)

ㄴ 다중표본화 기능

4.1.12 상주성

자원을 생성하면 자원이 GPU 메모리에 입주하며, 파괴되면 메모리에서 나간다.

함수로 직접 제어할 수도 있다.

ID3D12Pageable 배열을 매개변수로 사용한다.

MakeResident (올리기)

Evict (내리기)

 

4.2 CPU와 GPU의 상호작용

1. mCommandList에 set command, draw command같은 명령들을 추가한다. 

2. mCommandList->close()로 명령들의 기록이 끝났음을 알린다.

3. mCommandQueue->ExecuteCommandLists를 수행하여 GPU 명령대기열에 명령 목록을 제출하면

명령 대기열은 명령 목록에 담긴 명령 메모리 할당자(command allocator)를 참조한다. (명령 목록은 바로 reset 되어도 상관이 없음)

4. 명령 메모리 할당자는 GPU 명령 대기열의 참조가 완전히 끝난 후에 (대기열이 빈 경우) reset 해야 한다.

 

Direct3D 12 API에는 생성하고자하는 COM 인터페이스의 COM ID와 void** 를 받는 함수들이 많기 때문에 매크로를 정의하여 사용한다. 

#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)

4.2.2 CPU 동기화

mCommandQueue->Signal 함수를 이용

명령 대기열에 새 울타리 값을 갱신하는 명령(Signal)을 추가

 

울타리 값은 0부터 시작하는 정수, 새로운 울타리 지점을 만들때마다(명령 대기열 flush) 1씩 증가

cpu 울타리 값은 바로 증가하지만 gpu 울타리 값은 명령 대기열이 비어야 증가하기 때문에 

gpu 울타리 값이 cpu 울타리 값과 같아질 때까지 기다림

 

4.2.3 자원 상태 전이

자원에 상태를 부여하여 자원 위험 상황을 피하기 위해 존재

개발자는 자원이 언제 전이하는지 알고 있기 때문에 프로그램이 자원 전이를 추적하는 부담을 줄일 수 있다.

전이 자원 장벽(transition resource barrier)

mCommandList->ResourceBarrier함수 // 장벽(자원, 이전상태, 이후상태)의 배열을 명령 대기열에 추가

 

4.2.4 명령 목록을 이요한 다중 스레드 활용

장면 전체를 하나의 명령 목록으로 그리려고 하면 명령 목록을 만드는데 CPU 시간이 오래 걸릴 수 있음

4개의 스레드 마다 하나씩 명령 목록을 만들게 하면 CPU 시간이 1/4배가 됨

 

1. 각 스레드는 명령 목록과 명령 메모리 할당자를 독립적으로 가진다.

2. 명령 대기열에는 동시에 접근할 수 있다.

3. 성능상의 이유로 초기화 시점에 동시에 기록할 수 있는 명령 목록들의 최대 개수를 설정해야 한다.

다중 CPU 코어의 장점을 활용할 수 있다.

 

DirectX 기본 프로젝트 빌드 시 VS 2019 버전에서 일어나는 오류

잘 따라했는데 문제가 생긴다
vs2019의 c++ standard conformance check에서 발생한 문제

추가 옵션에 /permissive를 적어주면 해결된다.

'읽은 책 > DirectX 12를 이용한 3D 게임 프로그래밍 입문' 카테고리의 다른 글

5. 렌더링 파이프라인  (0) 2022.06.14
4. Direct3D의 초기화(2)  (0) 2022.06.13
3. 변환  (0) 2022.06.12
2. 행렬 대수  (0) 2022.06.11
1. 벡터 대수  (0) 2022.06.11

+ Recent posts