유니티 SRP Batch에 대해 #Draw Call #Batch #Render State

나는 문뜩 궁금해졌다. SRP Batch는 같은 Shader를 공유하는 메테리얼을 사용하면 드로우콜 비용이 줄어든다는 것 알게 된 이후 그렇다면 왜 굳이 Texture Altas를 사용하는 것인지? 너무 궁금해졌다.

 

왜냐하면 어차피 같은 Shader를 사용하면 다른 메테리얼 사용해도 SRP Batch덕분에 드로우콜 비용이 줄어드니깐 Texture Atlas를 사용해서 굳이 메테리얼을 하나로 만들어서 사용할 필요가 있을까?

 

야이 바보야 메테리얼 하나당 드로우콜 하나가 발생하는거잖아! 

어느 정도 맞는말이다.

 

Draw Call이란 것은 DP Call + Render State인데 DP Call은 무시하고 다른 메테리얼을 사용한다는 것은 다른 Render State를 사용한다는 것이므로, 같은 Shader를 사용하더라도 메테리얼이 가지고 있는 속성들을 다르게 사용하는 경우(Render State가 다르므로) 드로우콜이 증가하는 것이라고 봐도 될 것 같다.

 

드로우콜 비용이 증가한다고 보는게 더 정확하려나? 

 

참고로 Render State는 Unity에서 SetPass Call개념으로 이해하면 됩니다.

(좌) A 메테리얼 / (우) B 메테리얼

예를 들어, 같은 Shader를 사용하고 있다고 가정했을 때 A라는 메테리얼과 B라는 메테리얼이 존재한다고 생각해보겠습니다. 

A 메테리얼의 경우 Base Map만 사용하고 있고, B 메테리얼의 경우 Base Map과 Specular Map까지 사용하고 있습니다.

SRP Batch가 깨진다

두 메테리얼 모두 URP/Lit Shader를 사용하고 있음에도 불구하고 메테리얼이 사용하는 속성이 다르므로 SRP Batch가 깨지고 맙니다.

 

이런 경우에는 그냥 A, B 메테리얼 따로 분리해서 사용하는 것이 맞긴하다. 왜냐하면 사용하는 속성이 다르니깐.

 

근데 나는 이게 궁금한게 아니였다.

 

같은 Shader를 사용하고 메테리얼들이 같은 속성을 사용한다고 가정했을 때 굳이 Texture Atlas를 사용하여 메테리얼을 하나로 합칠 필요가 있는지? 가 궁금한것이였다.  

왜냐하면 같은 Shader를 사용하고 메테리얼들이 같은 속성을 사용하면 SRP Batch가 되므로 굳이 Texture Altas가 필요없는거 아닌가? 라는 의문이 너무 들었기 때문이다.

 

위 예시로 든 A,B메테리얼에서 B메테리얼의 Specular Map를 삭제하고 두 메테리얼 모두 Base Map만 사용하고 다시 프레임디버거를 찍어봤습니다.

 

SRP Batch가 제대로 된다

Batches수는 14개고 SetPass Call은 11개, SRP Batch가 제대로 동작하는 것을 볼 수 있습니다.

 

그렇다면 A,B 메테리얼을 C라는 메테리얼로 하나로 묶은 다음 비교해보면 어떻게 될까요?

뭐가 다를까

Batch수도 14개 SetPass Call도 11개, SRP Batch도 동일하게 작동합니다.

 

결국 Texture Altas를 사용하는 이유는 Base Map, Specular Map 등만 다르고 나머지 고유한 속성(Color 등)이 같으며 런타임동안 바뀌지 않는다고 보장받는다면 하나의 Texture Altas를 사용함으로써 Draw Call 비용을 줄일 수 있기 때문에 사용하는 것입니다.

 

출처 - https://docs.unity3d.com/Manual/SRPBatcher.html

SRP Batcher는 같은 Shader를 사용하는 여러 메테리얼을 한 번에 처리할 수 있지만, GPU는 각 메테리얼의 텍스처를 바인딩하는 작업을 따로 해야 하기 때문에 상태 변경으로 인한 비용이 발생합니다. 텍스처가 많을수록 이 비용이 더 커지므로, 텍스처 아틀라스를 사용하여 여러 텍스처를 하나로 합치면 이 문제(바인딩을 한 번에 할 수 있다)를 해결하고 성능을 최적화할 수 있습니다.

 

즉, 아까 설명했던 Draw Call = DP Call + Render State에서 Render State의 변화가 적어지므로 Draw Call 비용이 적어진다고 보면 될 것 같습니다.

 

쉽게 Draw Call이 감소했다고 볼 수 있을 것 같습니다.

 

그럼 무작정 모든 객체에 Texture Altas를 사용해야 하냐?

그건 아닙니다. 방금도 언급했다시피 결국 Texture Altas를 사용하는 이유는 Base Map, Specular Map 등만 다르고 나머지 고유한 속성(Color 등)이 같으며 런타임동안 바뀌지 않는다고 보장받을 때 사용하는 것이 좋습니다.

 

고유한 속성들이 다르면 그냥 다른 메테리얼 사용하는 것이 편합니다. 

 


Batch의 수를 줄이는 것은 DP Call을 줄이는 거라고 생각하면 될 것 같습니다.

Batch = Draw Call + Set Pass Call인데 여기서 Draw Call은 DP Call + Render State인데 쉽게 Render State를 빼고 DP Call만 생각하면 좋을 것 같습니다.

 

머리 안아프게 생각하는 방법 Batch = DP Call(Mesh Renderer가 가지고 있는 메테리얼의 개수, 왜냐하면 메테리얼 없으면 렌더가 안되니깐)인데, 이거는 언제까지나 같은 Shader를 사용하고 같은 메테리얼 속성을 사용한다고 생각하면 됩니다.

 

같은 Shader를 사용하더라도 만약 메테리얼들의 고유 속성들이 각기 다르다면 이때는 Batch = DP Call + SetPass Call이 되게 됩니다. 

 

SRP Batch는 Draw Call 개수를 감소하는 방법이 아닌 비용을 절감하는 기법입니다.

Draw Call 개수를 감소하는 기법의 경우 대표적으로 GPU Instancing이 있습니다.

 

유니티 GPU Instancing에 대해서 #동적 객체 최적화 방법

Instancing이란? Instancing은 주로 '복제' 또는 '반복 생성'의 개념을 뜻합니다. 특정 객체, 데이터, 또는 구조의 여러 인스턴스를 생성하고 관리하는 과정을 포함됩니다. 유니티에서 Instancing이라는 개

wlsdn629.tistory.com