Draw Call Count와 Batch Count의 차이 (Unity 5)

Unity가 5 버젼으로 넘어오면서 Stats 창에서 Draw Calls 의 갯수를 표현하는 부분이 사라졌다. 대신 Batches와 SetPass Calls 라는 항목이 생겼다. 여전히 Profiler에서는 Rendering 파츠에 Draw Calls가 있지만 Draw Call 대신 Batch를 줄이는라 표현으로 유도하는 의도가 보인다.

스크린샷 2015-04-28 오후 6.33.58

Official Doc에서도 http://docs.unity3d.com/Manual/DrawCallBatching.html 이야기한다. “중요한건 Batch Count야!!!” 라고.

 To draw an object on the screen, the engine has to issue a draw call to the graphics API (e.g. OpenGL or Direct3D). Draw calls are often seen as expensive, with the graphics API doing significant work for every draw call, causing performance overhead on the CPU side. However this is not the case. The expensive part is the changing of the resources accessed by the GPU between the draw calls as it triggers a graphics driver validation each time. The emphasis should be on reducing the batch count, rather than the draw call count.

자, 그런데 문제는 Draw Call과 Batch Count와 무슨 차이인가 라는 점이다. 평범한 Cylinder 하나를 그려도 Batch Count와 Draw Call Count는 정확히 일치한다. Batch Count가 늘어나면 Draw Call도 늘어나고 Draw Call Count가 늘어났을 경우 Batches 의 갯수도 늘어나 있고 그 숫자 또한 일치한다.

스크린샷 2015-04-28 오후 6.28.42

스크린샷 2015-04-28 오후 6.28.53

Multi-Sub 메쉬를 엔진에 얹어봐도 Batch와 Draw Call 수는 일치하고, Multi Pass Shader를 얹어봐도 Batch와 Draw Call 수는 일치한다. Dynamic Batching이 되는 Object를 얹어도 Batch Count와 Draw Calls 수는 일치하기는 마찬가지이다.
nVidia에서 내놓은 그 유명한 Batch Batch Batch 자료 2페이지를 보면, Batch를 이렇게 정의한다. http://www.nvidia.de/docs/IO/8230/BatchBatchBatch.pdf

Every DrawIndexedPrimitive() is a batch
– Submits n number of triangles to GPU
– Same render state applies to all tris in batch
– SetState calls prior to Draw are part of batch

즉, DirectX기준 DrawIndexedPrimitive(), OpenGL로 말하면 glDrawElements() 의 호출이 곧 Batch 라고 말한다. DrawIndexedPrimitive()이나 glDrawElements()의 호출은 Draw Call의 호출이지 왜 이게 Batch인가? 라는 생각이 든다. 이건 Batch와 Draw Call이 개념상 다르지만, 실제로 그 발생 횟수가 일치한다는 말이다. Batch는 CPU가 GPU에게 건내주는 택배 박스라고 생각하면 이해가 좀 수월하지 않나 싶다. Command Buffer상의 SetState()를 호출하는 작업과 그려질 Triangle의 정보들을 셋팅하는 작업, Rendering State를 셋팅하는 작업들이 다 이에 해당한다. Batching이 다 끝나면 GPU에서 “택배 받으세요” 하고 넘겨준다. 따라서 1회 Batching이 끝나면 1회 Draw Call이 발생하게 된다.

Unity에서 고정 Object에 대해서 체크를 해주면 Static Batching이, 300개 미만의 Vertex를 가진 Object에 대해서 Dynamic Batching이 발생하지만 동일 Material, 동일 Shader를 쓴다는 가정하에 발생한다. 그리고 Batching이 발생한 후에는 즉시 Draw Call이 발생한다는 의미이다.

따라서, Draw Call이 없어지고 갑자기 왜 Batch가 들어왔는가? 라는 질문에 대한 답변은 그동안은 게임 개발하다가 “Draw Call의 갯수 줄이세요~” 라고 이야기 했다면, 이제부터는 “Batch 갯수를 줄이세요~” 라는 말로 바꿔달라는 유니티의 정책적 의도로 받아들여야 할 것 같다. (그거나 그거나… -_-;)

하나 확실한 것은 Draw Call도 Batch도 항상 가능한 줄여야할 녀석들이라는 점~ ㅎ

관련하여 Unity Forum에서 나눠진 논의들…
http://forum.unity3d.com/threads/draw-calls-vs-batches-optimization-unity-5.318704/#post-2088565