본문 바로가기
Unity

[Unity] 드로우 콜과 배칭 (그래픽스 최적화 스타트업)

by 소리쿤 2022. 7. 25.
작성자의 이해가 잘못 됐을 수 있습니다. 참고용으로 읽어주시기 바랍니다. 지적은 항상 감사합니다.

 

드로우 콜?

 

드로우 콜은

(1) 오브젝트를 렌더링하는 데에 필요한 데이터(메시, 텍스처, 쉐이더 등)를 CPU 메모리에서 GPU 메모리로 복사하는 과정

(2) DP Call (Draw Primitive Call) - GPU의 Render State 테이블을 기반으로 렌더링하라는 명령

 

두 과정으로 나뉘어집니다.

 

(1)

데이터는 디스크 > CPU 메모리 > CPU > GPU 순서로 이동하며,

이를 로딩 시점에 CPU 메모리에 미리 적재해두었다가,

드로우 콜 시점에 GPU의 각 슬롯에 복사해넣고,

GPU에 데이터를 기반으로 슬롯 당 Render State 테이블을 만듭니다.

 

이 이후에 DP Call을 수행하는 것입니다.

 

(2)

DP Call로 인한 렌더링은 그래픽 칩셋에서 진행되며, 이는 OS마다 다릅니다.

Unity의 DP Call은 그래픽스 API를 통해 여러 OS에 대응할 수 있습니다.

 

API를 호출하면, 드라이버 칩셋에 맞는 신호로 명령을 바꾸어 전달하기 때문에

이 과정에서 오버헤드가 발생합니다.

 

드로우콜은 CPU > GPU 메모리 복사 및 DP Call로 이루어지므로 CPU 바운더리라고 볼 수 있습니다.

 

결과적으로 드로우 콜은 텍스처 크기나, 메시 수 조절로 성능 향상을 기대할 수 없고,

횟수를 줄이는 방식으로 대응해야 합니다.

 


Set Pass와 Batch

 

드로우 콜은 뒤에서 말했 듯, 여러 가지 과정을 복합적으로 의미하기 때문에,

Unity는 이 드로우 콜에 대한 최적화를 위해 큰 개념으로 

 

(1) Set Pass - 쉐이더로 인한 렌더링 패스 횟수

(2) Batch - 드로우 콜 횟수

 

로 나누었습니다.

 

기본적으로...

SetPass는 렌더링에 사용된 Material 수와 같습니다.

Batch는 렌더링에 사용된 오브젝트의 수, 즉 드로우 콜 수와 같습니다.

 

Batch가 많더라도, SetPass가 적으면 GPU State 테이블 내 변경점이 적기 때문에 좋고,

SetPass가 많더라도, Batch가 적으면 콜 자체가 적기 때문에 좋습니다.

물론 둘다 줄이는 게 좋겠지요.

 

다만 Batch를 줄이기 위해 오브젝트 수 자체를 줄이는 것은 힘들 것입니다.

그래서 Unity에서는 `Batching`을 합니다.

 

`Batching`은 여러 드로우 콜을 묶어 하나의 Batch로 만드는 것을 의미합니다. 

 


 

1. 같은 Material 인스턴스를 사용하는 여러 오브젝트는 한 번의 Batch에 그릴 수 있다.

 

> Material에 사용되는 여러 텍스처를 아틀라스로 묶어서 하나의 Material로 만들고, UV 좌표를 제어하여 사용하는 것이 방법이 될 수도 있음

그렇다고 무작정 합치면, 텍스처 아틀라스가 고 해상도가 되어 대역폭이 모자라 이슈가 될 수도 있음.

 


 

2. Static Batching 사용

https://docs.unity3d.com/Manual/static-batching.html

 

Unity - Manual: Static batching

Static batching Static batching is a draw call batching method that combines meshes that don’t move to reduce draw calls. It transforms the combined meshes into world space and builds one shared vertex and index buffer for them. Then, for visible meshes,

docs.unity3d.com

edit > project setting > player

Static Batching은 다음 체크 박스를 체크한 오브젝트에 대하여 수행됩니다.

Static이 체크된 오브젝트들은 앞으로 움직이지 않는 하나의 오브젝트라고 가정되며,

버텍스 연산을 런타임에 수행하지 않고 미리 수행하여 저장합니다.

 

기본적인 메시 데이터 외에도 static이 체크된 오브젝트들이 합쳐진 거대한 메시가 하나 더 저장되기 때문에

메모리가 추가 공간이 필요합니다. 

안 켰을 때
켰을 때, Saved by batching 2

기본적으로, 씬에 미리 배치돼있는 오브젝트만 스태틱 배칭 대상이 됩니다.

런타임에 추가되는 오브젝트를 스태틱 배칭하고 싶다면,

https://docs.unity3d.com/ScriptReference/StaticBatchingUtility.Combine.html

 

Unity - Scripting API: StaticBatchingUtility.Combine

Static batching is a draw call batching method that combines meshes that don't move to reduce draw calls. For more information about static batching, see Static batching. This method copies the mesh data of the GameObjects into a single internal mesh. Each

docs.unity3d.com

위를 참고해봅시다.

 

또한, 하나의 거대한 메시를 가진 오브젝트를 씬에 배치하는 것보다,

여러 작은 오브젝트를 가지고 조합한 후, 스태틱 배칭을 이용하는 것이 좋을 수 있습니다.

당연하지만 작으면 컬링될 확률이 높다. 크면 살짝만 보여도 배치에 그대로 반영된다.


3. Dynamic Batching 사용

다이나믹 배칭은 매 프레임 static 플래그가 체크되어 있지 않은 오브젝트를 모아서 합친 후, 

다이나믹 배칭용 버텍스, 인덱스 버퍼에 담아 렌더링합니다.

 

매 프레임마다 데이터 구축, 갱신이 일어나므로 오버헤드가 발생합니다. 

 

> 버텍스가 근 300 이상인 오브젝트는 다이나믹 배칭 대상에서 제외됩니다. (CPU 오버헤드 큼)

> Skinned Mesh에는 적용되지 않습니다. (이 메시의 스키닝 연산은 GPU에서 고속으로 수행됨)

 

일반 Mesh의 스키닝 연산은 CPU에서 수행되는데,

PlayerSetting의 GPU Skinning을 체크하여 GPU에서 수행하게 할 수도 있다.

 

이는 유니티의 그래픽스 API 지원에 따라 적용에 의미가 있고 없고가 결정될 수 있다. 

2021.3.7 ver 기준은 다음과 같다.

DX11 / ES3 (PC)
OpenGL ES3.1 or Vulkan (안드로이드)