
Component object model(COM)은 DirectX의 프로그래밍 언어 독립성과 하위 호환성을 가능하게 하는 기술이다. C++ 클래스로 간주하고 사용해도 무방하기 때문에 주로 COM 객체라고 흔히 부른다.
COM 객체는 생성을 위한 별도의 API 함수를 써야 한다.
모든 COM interface는 IUnknown COM interface의 기능을 상속한다.
COM 객체의 template smart-pointer이다. 이는 자동으로 메모리 관리를 해준다.
Microsoft::WRL::ComPtr class (#include <wrl.h>)
WRL: Windows runtime C++ template library
ComPtr은 기본적으로 ->, * 연산자에 대해 오버로딩 되어있고 다음의 세 가지 주요 methods를 갖는다.
Get: it returns a pointer to the underlying COM interface
GetAddressOf: it returns the address of the pointer to the underlying COM interface (포인터의 주소(포인터의 포인터)를 반환한다.)
Reset: it sets the ComPtr instance to nullptr and decrements the reference counter of the underlying COM interface (nullptr로 만들기, counter도 줄여줌)
각 차원의 원소에 해당 픽셀의 정보를 저장하는 행렬이다.
단순 이미지의 정보만 표시하는 것이 아닌 원소의 색상, 3차원 벡터등 다양한 정보를 담는다.
R: red, G: green, B: blue, A: alpha
U: unsigned, S: signed, NORM: normalized to [0,1] .(unsigned) or [-1, 1] .(signed)DXGI_FORMAT_R8G8B8A8_UNIT: 각각의 요소가 8 bit unsigned integer를 갖음 [0, 255] 범위
buffer가 한 개 있으면 원래 있던 화면을 지우고 출력해야해서 깜빡거리는 문제 flickering이 발생한다. 이를 해결하기 위해 화면에 출력할 front buffer와 뒤에서 그릴 back buffer를 나눈 뒤, 이들을 swap 해가며 관리한다. back buffer에 그림을 다 그리면, front buffer와 back buffer를 swap 한다.

카메라에서 물체까지의 거리 정보를 저장할 Buffer이다.
가능한 깊이 값은 정규화된 값 [0, 1]을 갖는다.

near과 far 사이에 있는 것만 투영하게 된다.
P의 depth 값은 p1으로 저장하게 된다.
depth buffer 또한 texture이다.
dissolves나 decaling, outlining등을 표현하는 Buffer이다.
Resources는 대부분 Buffer이다.
GPU는 resources를 읽거나 쓰면서 사용한다. GPU의 메모리는 작기 때문에 렌더링 전에 resource들을 rendering pipeline에 bind 해야한다.
Buffer들을 모두 pipepline에 올리는 것은 무겁기 때문에 실제로 bind 하는 것은 descriptor 객체이다. 이는 GPU resource를 표현해주는 가벼운 구조체이다.
descriptor들을 모아두는 힙이다.
초기화 시점에 한번만 만들고 런타임 시점에서는 Readonly로 사용된다.
픽셀이 무한히 작지 않기때문에 선이 완벽하게 그려지지 않는 현상이다. 이를 해결하기 위한 안티 앨리어싱방법을 알아보자.

back buffer와 depth buffer를 해상도의 4배로 그린 뒤(더 정교하게 표현 됨), 화면에 출력해야 할 때, 이 4픽셀들을 하나의 픽셀로 합치는 것이다. 이렇게 원래의 해상도로 줄인다.
MSAA는 도형의 가장자리(Edge)만 여러 개의 샘플로 처리해서 계단현상(Aliasing)을 줄이는, 성능 대비 효과가 좋은 안티앨리어싱 기법이다.
예: 한 픽셀에 대해 4개의 샘플 포인트를 찍음
픽셀이 도형의 안에 완전히 들어가 있으면 → 그냥 1개로 처리
픽셀이 도형의 경계에 걸쳐 있으면 → 4개의 샘플을 평균해서 부드럽게 만듦

GPU가 지원하는 기능의 집합을 말한다.
GPU가 기능수준11을 지원한다고 하면, DX11의 기능 모두 지원해야한다.
사용자의 기능 수준이 낮을 경우 실행을 포기하는 대신 품질을 낮추는 방법을 택할 수 있다.
DirectX Graphics Infrastructure는 Direct3D와 그래픽 하드웨어(드라이버, 출력 장치) 사이를 연결해주는 중간 계층 API이다.
스왑 체인, 어댑터 선택, 출력 등을 관리해주는 중간 관리자 역할을 한다.
역할 요약
- 스왑 체인 관리: 화면 출력용 Back Buffer/Front Buffer 관리
- 디스플레이 설정: 해상도, 리프레시율 등 디스플레이 관련 설정
- GPU 어댑터 선택: 시스템에 있는 그래픽 카드(어댑터) 선택
- 리소스 공유: 여러 장치 간의 리소스를 공유할 수 있게 함
- 창 모드/전체 화면 전환: 윈도우 모드 ↔ 전체 화면 모드 스무스하게 전환 가능
- 먼저 GPU 및 디스플레이 관련 객체인 IDXGIFactory를 생성한다.
이는 어댑터(GPU)검색과 swap chain 생성을 담당한다.
- 그 다음 IDXGIAdapter를 생성한다.
이는 컴퓨터 안의 CPU를 나타낸다. 컴퓨터의 어떤 GPU를 쓸지 고를 수 있다.
- 이후 D3D12CreateDevice로 선택된 GPU에 대해 Device를 생성한다.
- ID3D12Device 생성됨
만들어진 device는 buffer, texture를 만들고 GPU에 렌더링 명령을 보내는 역할 등을 한다.
GPU 리소스를 생성하고, 커맨드 큐/리스트를 관리한다.
즉, GPU 리소스와 렌더링 명령을 다루는 객체로 볼 수 있다.
복잡한 resources를 사용할 때, resource를 GPU에 상주시킬 것이냐, 떼서 쓸 것이냐를 관리할 수 있다. resource들을 필요한 경우에만 GPU에 상주시키면 되기 때문이다.
GPU가 CPU가 명령한 것을 하나 하나 처리하면 병목과 오버헤드가 많이 발생할 것이다. 그렇기 때문에 GPU는 Command Queue를 갖고 있고, CPU는 명령 들을 allocator를 통해 저장한 후 Command list에 기록한다. 그 후 이 명령 list를 command queue에 제출하고 GPU가 명령을 실행한다.
GPU에서 수행할 명령을 묶어서 처리하는 것이다.

d3d에서 CPU가 GPU에게 전달할 명령을 직접 메모리에 저장하지 않고 allocator를 통해 명령을 저장 후 명령 리스트가 이를 활용하는 이유는 CPU가 명령을 기록하는 동안, GPU는 이전 프레임의 명령을 실행할 수 있어야 하기 때문이다. 명령 리스트는 GPU가 실행 중일 수 있기 때문에 직접 명령을 저장할 수 없고 따라서, 명령 allocator를 사용하여 GPU가 실행 할 명령을 기록하는 것이다.
즉, 명령 리스트는 GPU에 전달할 명령을 기록하는 객체이고, allocator는 명령을
저장하는 메모리 공간이며, 명령 리스트가 참조하는 메모리라고 볼 수 있다.
GPU가 리소스를 처리하고 있을 때, CPU가 접근을 하면 예상치 못한 동작이 발생할 수 있다. 이가 race condition이며, 이를 막기위해 GPU가 작업을 다 끝낼때까지 CPU가 리소스를 건들지 못하게 막을 수 있다.

CPU와 GPU 간의 작업 순서를 동기화하기 위해 GPU가 작업이 다 끝날때까지 CPU의 접근을 막는다.
작동 방식
- GPU에게 작업을 보내고, fence 값(예: 1)도 같이 설정함
- CPU는 fence 값을 폴링하거나 기다림
- GPU가 작업을 끝내면 fence 값을 1로 업데이트
- CPU는 GPU 작업이 끝났음을 알게 됨
GPU에서 같은 리소스를 동시에 여러 용도로 쓰려고 할 때 발생하는 충돌 문제인 Race Hazard가 발생할 수 있다.
이를 해결하기 위해 DirectX에서는 자원들마다 상태를 지정하여 관리한다.
GPU 리소스는 한 번에 하나의 용도로만 안정적으로 사용할 수 있다. 예를 들어, 같은 텍스처라도 렌더 타겟으로 쓰다가 픽셀 셰이더에서 읽으려면 상태를 Render Target → Shader Resource로 변환(Transition)해야 함.
Resource Transition = 리소스 상태를 바꾸는 작업
Barrier = 그 상태 전환을 GPU에게 알려주는 명령
D3D는 효율적인 멀티 스레딩을 하도록 설계되었다. Command list는 멀티 스레딩을 하도록 설계되었다.
예를 들어 많은 오브젝트가 있는 장면에서 이들을 렌더링할 command list가 있는 상황이다.
"여러 스레드가 각자의 Command List에 작업을 병렬로 기록하고, 이후 이 Command List들을 Command Queue에 제출하여 GPU에서 실행하게 한다"