1. CPU와 GPU의 상호작용
CPU에서 GPU에 명령하기
일반적으로 CPU에서 렌더링, 상태 변경 등의 명령을 GPU에 전달한다. 그런데 GPU가 바쁘게 작업하는 도중이라면, CPU는 GPU의 작업이 끝나기를 하염없이 기다리게 될 수 있다. 따라서 커맨드 패턴(Command Pattern)과 메시지 큐(Message Queue)에 의한 비동기 방식을 활용한다. CPU에서 GPU에 전달할 명령(Command)을 임시 공간에 담아 두고, GPU가 여유 될 때 명령을 하나씩 꺼내어 처리한다.
Command Buffer(커맨드 버퍼)
CPU의 각 스레드에서는 GPU에 전달할 렌더링 관련 명령을 모듈화하여 커맨드 버퍼에 차곡차곡 쌓아 임시로 저장한다. 그리고 GPU의 공유 커맨드 큐에 전송한 뒤, GPU를 기다리지 않고 다른 작업을 수행할 수 있다. 각 스레드마다 커맨드 버퍼를 갖고 공유 큐에 전송할 수 있으므로, 멀티스레드를 활용한 병렬 처리에도 용이한 방식이다. 명령을 곧장 커맨드 큐에 전송하는 것은 데이터 동기화 문제로 인한 성능 저하를 유발할 수 있으므로, 명령들을 모아 버퍼 단위로 전송하는 방식을 사용하는 것이다.
Command Queue(커맨드 큐)
GPU에는 CPU와 GPU가 함께 공유하는 커맨드 큐가 존재한다. GPU는 여유가 될 때마다 커맨드 큐에 담긴 커맨드 버퍼를 차례로 꺼내어, 그 안에 담긴 명령들을 처리한다.
2. 드로우 콜
Render States(렌더 상태)
GPU가 렌더링을 수행하기 위해 필요한 정보들 쉐이더, 메시, 텍스쳐, 알파 블렌딩 옵션, ZTest 및 스텐실 옵션 등이 있다.
Render State Changes(렌더 상태 변경)
GPU에서 렌더링할 대상의 상태가 변경될 경우 수행된다. CPU가 GPU에 렌더 상태 정보를 전송하며 상태 변경 명령을 보낸다.
SetPass Call
쉐이더로 인한 렌더 상태 변경만을 의미한다. 쉐이더 내의 Pass 변경, 쉐이더(마테리얼) 자체의 변경, 쉐이더 내 파라미터들의 변경에 해당된다. 메시의 변경은 렌더 상태 변경이지만, SetPass Call에는 해당되지 않는다. 따라서 메시가 달라도 마테리얼이 같다면 SetPass Call은 딱 1번만 발생한다.
DP Call(Draw Primitive Call)
CPU가 GPU에 그리라는 명령을 직접적으로 호출하는 것(예 : glDrawElement()) 그려야할 대상의 정보가 조금이라도 달라지는 경우, DP Call에 앞서 렌더 상태 변경이 동반된다. GPU는 현재 렌더 상태 정보를 기반으로 렌더링을 수행한다.
Draw Call
CPU에서 GPU에 렌더링 명령을 전송하는 것 Render State Changes + DP Call 과정을 통칭한다.
3. 배칭
Batch
SetPass Call + DP Call Render State Changes가 아니라 SetPass를 포함하므로, Draw Call보다 좁은 의미를 가진다.
Batch가 적다고 Draw Call 자체가 적은 것이 아닐 수 있다. Batch는 메시 상태 변경을 포함하지 않으므로, 배칭 처리가 되었더라도 메시가 다양하면 실제로 Draw Call은 훨씬 많을 수 있다. Batch는 메시의 변경을 포함하지 않는다. 메시가 달라도 마테리얼이 같으면 하나의 Batch로 통합할 수 있다.
Batching
여러 개의 Batch를 하나로 묶는 최적화 기법
Static Batching
런타임에 움직이지 않는 메시들에 대해서만 가능하다. 여러 개의 메시를 하나의 메시로 통합한다.
메시를 통합한 만큼, 하나의 배치로 그려줄 수 있다. 인스펙터에서 Batching Static 플래그를 설정하면 된다. Static Batching이 되더라도 컬링 연산은 원래의 메시 기준으로 이루어진다는 장점이 있다.
Dynamic Batching
유니티에 의해 내부적으로 자동으로 수행된다. 플레이어 설정에서 Dynamic Batching만 켜주면 된다. 실제로는 제약이 너무 많으므로 Dynamic Batching에 의한 최적화를 기대하기는 힘들다. 예를 들어, 스킨 메시에 대해서는 적용되지 않으며 버텍스 300개 이상의 메시에 대해서도 적용되지 않는다.
GPU Instancing
동일 메시, 동일 마테리얼인 경우에만 가능하다. 쉐이더에서 인스턴싱 사용 여부를 명시해주어야 한다. 쉐이더에서 Instancing Buffer 영역을 선언하여 인스턴싱을 적용할 쉐이더 파라미터를 설정할 수 있다. 마테리얼에서 Enable GPU Instancing에 체크하여 인스턴싱을 적용할 수 있다. 배칭이 적용됨에도 불구하고 Material Property Block을 통해서 마테리얼마다 파라미터를 변경할 수 있다는 장점이 있다.
SRP Batcher
유니티의 Scriptable Render Pipeline에서만 동작한다. 동일 쉐이더, 다른 마테리얼에 대해서도 적용된다. 쉐이더 배리언트에 대해 특정한 규칙을 만족하는 경우에만 적용될 수 있다.
출처 : https://rito15.github.io/posts/unity-draw-call-and-batching/
'그래픽스 > 공통' 카테고리의 다른 글
곡선 (Curve) & 스플라인 (Spline) (0) | 2024.01.21 |
---|---|
Ambient and Diffuse Lighting / 환경 및 반사되는 광원 (0) | 2023.07.11 |
그래픽스 파이프라인 (게임 엔진 관점) (0) | 2022.10.31 |
셰이더란? (Shader) (0) | 2022.10.30 |
그래픽스 API 정의와 비교 분석 (0) | 2022.09.04 |