포스트

렌더링 파이프라인 - 0

렌더링 파이프라인이 동작하기 전에 발생하는 작업들에 대해서 공부하고 정리했습니다.

렌더링 파이프라인 - 0

오브젝트가 화면에 그려지는 것은 한 번에 일어나지 않는다.
오브젝트를 화면에 그리기 위한 일련의 작업들이 있는데 이를 렌더링 파이프라인이라고 한다.

렌더링 파이프라인을 거쳐 화면에 물체가 렌더링되기 전에 반드시 거쳐야 하는 일련의 작업이 있다.



그래픽스 API 초기화

기본적으로 GPU 내부에는 다음과 같은 파이프라인이 존재한다.

1
2
3
4
5
6
7
8
9
Input Assembler
      ↓
Vertex Shader
      ↓
Rasterizer
      ↓
Fragment Shader
      ↓
Output Merger

그래픽스 API 초기화를 거쳐서 GPU와 통신할 수 있는 컨텍스트를 생성한다.
그래픽스 API 초기화 대부분의 과정은 CPU에서 일어난다.


GPU 디바이스 생성

그래픽스 API 초기화에서 가장 먼저 GPU 디바이스를 생성한다.
GPU 디바이스는 현재 기기의 GPU를 추상적으로 표현하는 오브젝트다.

GPU 디바이스는 프로그램이 시작될 때 단 한 개만 그리고 단 한 번만 생성한다.

GPU 디바이스가 생성되면 커맨드 큐와 연결되고, GPU에게 보낼 명령을 받아들인다.
즉, GPU에게 명령을 전달한다는 의미는 GPU 디바이스에게 명령을 전달한다는 의미다.


커맨드 큐 생성

커맨드 큐

커맨드 큐GPU에게 전달할 명령을 보관하는 스케줄러다.
커맨드 큐는 프로그램이 시작될 때 단 한 개만 그리고 단 한 번만 생성한다.

CPU와 GPU는 직접 통신하지 않기 때문에 커맨드 큐가 필요하다.

CPU는 코어 수가 적지만 GPU는 수천 개의 코어를 가지고 있다.
GPU는 대량 병렬 연산에 특화되어 있다.

CPU와 GPU가 직접 통신하여 둘이 동기화가 되면 GPU는 CPU의 작업 처리를 대기하게 되면서 성능 낭비가 발생한다.

이러한 이유로 CPU와 GPU는 직접 통신을 하지 않는다.
그래서 GPU가 작업을 하는 도중에 CPU가 명령을 보내는 경우가 존재한다.
하지만 GPU는 작업 중이라 처리할 수 없기 때문에 커맨드 큐에 순차적으로 명령을 스케줄하게 된다.


커맨드 버퍼

커맨드 큐 내부에는 커맨드 버퍼가 기록되는데 CPU에서 GPU에 보낼 명령들을 보관한다.
이 명령들은 일반적으로 GPU에게 전달할 데이터GPU가 실행할 행동을 표현한다.

커맨드 버퍼에 있는 명령이 나중에 GPU에게 전달될 때 명령에 포함된 데이터들은 RAM에서 GPU 내부의 VRAM으로 복사된다.
이 데이터들에는 텍스처, 정점, 셰이더 정보가 여기에 포함된다.

CPU는 실행할 명령들이 담긴 커맨드 버퍼를 계속 커맨드 큐에 등록하게 된다.
그리고 GPU의 작업이 끝난 순간, GPU는 커맨드 큐에서 커맨드 버퍼를 가져가서 작업을 실행한다.

즉, CPU가 명령과 커맨드 버퍼를 생성하는 것은 GPU에게 보낼 명령을 예약하는 것d이다.



파이프라인 상태 객체 생성

파이프라인 상태 객체(Pipeline State Object: PSO)들은 렌더링 파이프라인의 현재 상태를 표현한다.
하나의 PSO는 해당 PSO에 대응하는 렌더링 파이프라인에 사용할 속성들을 가진다.


렌더링 파이프라인 서술자

하나의 PSO 내부에는 렌더링 파이프라인 서술자(Rendering Pipeline Descriptor: PSO Desc)가 존재한다.

PSO Desc는 렌더링 파이프라인이 어떤식으로 동작할지를 표현하는 오브젝트다.
PSO Desc의 내부에는 다양한 필드들이 존재하는데 중요한 부분은 InputLayout의 정점 서술자다.

1
2
3
4
5
6
7
8
9
10
11
D3D12_GRAPHICS_PIPELINE_STATE_DESC
 ├─ VS  ← Vertex Shader
 ├─ PS  ← Fragment Shader
 ├─ RasterizerState
 ├─ BlendState
 ├─ DepthStencilState
 ├─ InputLayout   ← 여기 ★ 
 ├─ PrimitiveTopologyType
 ├─ RTVFormats
 ├─ DSVFormat
 └─ RootSignature

커맨드 큐에서 GPU로 커맨드 버퍼를 불러올 때 명령은 스트림의 형태로 전달된다.
정점 서술자는 스트림 형태로 전달되는 명령을 구조체처럼 해석할 수 있도록 메타 데이터를 정의한다.

PSO는 여러 개 생성할 수 있다.
따라서 각각 다른 셰이더를 사용하는 렌더링 파이프라인을 선택해서 명령을 실행할 수 있다.



사전 데이터 로드

마지막으로 모델이나 텍스처 등 사용할 데이터들을 RAM에 미리 로드한다.
GPU로 어떤 오브젝트를 화면에 그리기 위해서는 VRAM에 복사할 데이터를 준비해야 한다.



드로우 콜 생성

드로우 콜이란 CPU가 GPU에게 오브젝트를 렌더링을 지시하는 명령을 말한다.
즉, 드로우 콜 생성은 CPU에서 실행된다.



마무리

이번에 알아본 내용은 그래픽스 API 초기화와 드로우 콜 생성이다.
각각에서 살펴본 세부 단계는 다음과 같다.

1
2
3
4
5
6
7
그래픽스 API 초기화    →     [GPU 디바이스] 생성
       ↓                           ↓
드로우 콜 생성               [커맨드 큐] 생성
       ↓                           ↓
렌더링 파이프라인             [파이프라인 상태 객체] 생성
       ↓                           ↓
화면에 오브젝트 출력          [리소스 프리로드]             

여기까지는 Unity에서 처리해주는 단계기 때문에 사람이 건들일 일은 전혀 없다.
다음 글에서는 렌더링 파이프라인에 대해서 본격적으로 정리하도록 하겠다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.