Unity

[Unity][최적화] Batching, Draw Call, SetPass calls

자가라o 2021. 6. 30. 04:19

 

Batching(배칭)

동일한 메테리얼을 공유하는 복수의 드로우콜을 하나로 묶어서 드로우콜하는 기법

Batching = Draw Call + SetPass calls

Unite Seoul 2016 그래픽 최적화 세션中

▶Draw Call(드로우콜)

  • CPU가 GPU에게 화면에 오브젝트를 그려달라고 요청하는 것
  • 한프레임에서 오브젝트를 하나 그릴때 여러 정보들이 CPU에서 GPU로 전달
    • DATA > Storage(HDD,SDD,SD) > CPU Memory > GPU Memory
  • 매 프레임 화면에 그려야 하기 때문에 값이 클수록 프레임에 부하가 걸린다.
  • 적정개수 
    • PC : 1000개 이상 가능 ~ 3000개
    • 모바일 : 100개도 많다. 최신 디바이스는 200개까지가능
  • 일반적으로 오브젝트 단위로 1개씩 증가, 쉐이더에 따라서 추가적으로 증가

 

SetPass calls

메테리얼의 설정

- 쉐이더로 인한 렌더링 패스 횟수

- 메시, 텍스쳐, 쉐이더, 라이트등의 정보

- 하나의 설정으로 여러개의 드로우콜을 처리할 수 도 있다.

- 한개의 쉐이더 내에서 Multi-pass로 2번이상 렌더링을 거치면 2번의 드로우콜이 발생한다.

- renderer 옵션의 sorting layer 를 통해 동일한 메테리얼들을 하나로 묶어서 그리면 메테리얼 교체 비용이 줄어든다.

- 유니티 프로파일러 Rendering섹션에서도 확인 가능하다고 한다.


+ 동적(Dynamic)/정적(Static) 배칭

사용상의 차이는 Static 활성화 여부차이

- 동적배칭 -

  1. 동적으로 움직이는 오브젝트끼리 batch + static 플래그가 체크 되어있지 않은 오브젝트 대상으로 유니티가 알아서 해준다. OtherSettings에서 Dynamic Batching 플래그만 켜주면 된다.
  2. 버텍스가 너무 많은 메시는 버텍스를 수집하면서 오버헤드가 드로우콜보다 높아져서 제외된다.
  3. CPU를 이용해 World Space로 Transform하는데 걸리는 시간 < GPU를 이용해 World Space로 Transform하는데 걸리는 시간 + Render State를 바꿔서 Draw하는데 걸리는 시간인 경우 사용한다.

효율에 관해서는 그렇게 좋다고는 안 하더라

그냥 드로우콜보다 효율이 안좋은 경우도 있다고 한다.

조건도 까다롭다.

 

- 정적배칭 -

Static은 주로 변화(위치,회전,스케일등)가 없는 구조물 오브젝트에 사용되는데

충돌관련해서 최적화할때만 쓰이는줄 알았더니 배칭에도 영향이 있었다.

 

  1. 메모리를 희생해 성능을 올린다.
  2. 동적배칭보다는 효과가 좋아 CPU의 부담을 줄일 수 있지만 메테리얼을 메모리에 올려놓고 사용하기 때문에 적은 메모리를 사용해야 한다거나 과도하게 많은 오브젝트를 사용할 때는 피해야 한다.
  3. Static을 켜주면 로딩타임에 자동 배칭.
  4. 통으로 제작시 화면에 일부만 보이더라도 전체 처리를 해야하기 때문에 적절히 모듈화 방식으로 제작하면 성능상 유리하다.
  5. 런타임중에도 추가가능 하지만~ 데이터 수집+재생성 하기때문에 부하가 있음

 

- 설정 -

Edit > ProjectSetting > Player > OtherSettings에서 설정을 세팅할수있다.

디폴트 설정

- 2D 스프라이트 Batching -

2D는 버텍스가 적어서 batching이 훨씬 효율적.

Static/Dynamic 설정이 안되어있어도 자동으로 배칭된다.

 

- SRP 배칭(SRP Batch) -

메테리얼과 오브젝트의 정보를 GPU메모리에 상주시켜 시용한다.

다른 메테리얼을 쓰지만 색을바꾸거나, 오브젝트가 static하지 않는 것이 그다지 큰 퍼포먼스 저하를 가져오지 않게 된다.

같은 쉐이더를 쓰는 서로다른 메테리얼이 배칭된다.

https://mathmakeworld.tistory.com/55?category=405362 

 

- GPU Instancing -

많은 양의 동일한 개체를 그릴때

데이터를 검색하는데는 약간 느리지만 CPU에서 많은 양의 동일한 개체를 렌더링 하는 속도가 매우 빠르다.

한번의 드로우콜로 오브젝트의 여러 복사본을 렌더링 하다는 점은 배칭과 같다.

배칭은 CPU에서 지오멤트리 정보들을 연산해 합친 메시를 새로 만들어내는 과정을 거치고 GPU가 이를 가져다 렌더링 하지만 GPU인스턴싱은 인스턴싱되는 오브젝트들의 트랜스폼 정보를 별도의 버퍼에 담고 GPU는 이 버퍼와 원본메시를 가져다가 여러오브젝트를 한번에 처리한다.

인스턴싱 처리를 GPU에서 하기 때문에 GPU에서 메시를 재구성하는 하는 오버헤드나 메모리 이슈로부터 자유롭다.

오버헤드로 인한 제약이 적어서 원본메시의 버텍스 개수와 상관없이 런타임에서 동적인 오브젝트들을 배칭 처리할 수 있다.

 

해당 material에 적용가능하다면 체크박스가 생긴다.

 

https://docs.unity3d.com/kr/2018.4/Manual/GPUInstancing.html


+ Draw Call 최적화를 위한 여러가지 기법

1) Sprite Atlas

 

텍스처를 하나로 묶어 메테리얼을 일괄적으로 처리 가능하게 만들어주는 방법

 

Sprite 애니메이션처럼 한 파일안에 여러장의 이미지를 사용하는 경우가 있다.

이경우에는 Sprite Inspector > Sprite Mode에서 Multiple을 사용하여 묶여있는 이미지를 쪼개서 사용하게 되는데

이렇게 사용하는 경우 그 파일 안의 이미지만 사용했다면 몇장을 사용하든 Batch는 1밖에 증가시키지 않는다.

이미지를 쪼갰다하더라도 사실 한장의 이미지를 공유하지 때문에 CPU는 전체 이미지를 메모리에 올려놓고 그안에서 사용되는 이미지는 잘라서? 사용되기 때문이다.

이렇게 이미지를 미리미리 묶어서 사용하면 최적화에 좋겠지만 사실 그러기엔 너무 힘들다.

 

Sprite Atlas는 위와 같은 과정을 유니티안에서 가능하게 해준다.

낱개의 이미지들을 SpriteAtlas라는 커다란 스케치북안에 정리해서 한장으로 만들어 주는데

사용해 보면 같은 아틀라스에 들어있는 이미지들은 역시 몇장을 사용하든 Batch를 1밖에 증가시키지 않는다.

 

지금은 2048사이즈를 문제가 생기지않는 최대로 보고

이미지의 양이 많아져 2048*2048로도 담을 수 없게 되면 페이지로 나뉘게 되는데

같은 Atlas를 사용하더라도 페이지가 다르면 batching되지 않는다.

 

2) Bake된 라이트 맵

 

오브젝트에 라이트를 때리게?되면 CPU는 실시간으로 빛에 대한 연산(색, 밝기, 반사, 그림자등)을 해야한다.

하지만 Editor에서 오브젝트와 라이트간의 상호작용이 변화가 없을 예정이라면

연산을 미리 이미지로 만들어버리는데 이를 (Baked)굽는다고 하고 해당 이미지를 라이트맵이라고 한다.

구울때는 시간이 걸리지만 라이트연산 성능 개선에는 효과가 좋다.

골라서 구울 수 있기 때문에 대부분 플레이어나 몬스터를 제외한 맵 위주로 사용된다.

 

3) 오클루전 컬링(Occulusion Culling)

 

Frustum culling 프러스텀 컬링     : 카메라 밖의 보이지않는 오브젝트의 렌더링을 무효화

Occulusion culling 오클루전 컬링  : 다른 오브젝트에 가려진 오브젝트의 렌더링을 무효화

Static체크를 해줘야한다고 한다.

 

https://docs.unity3d.com/kr/current/Manual/OcclusionCulling.html


그외 최적화 관련