Draw Call
Draw Call은 GPU에게 어떤 물체를 화면에 그리도록 지시하는 명령입니다.
간단히 말해서, Draw Call은 GPU에게 "이것을 그려라"라고 말하는 것과 같습니다.
Draw Call의 수가 많으면 많을수록 CPU와 GPU 사이의 통신이 늘어나며, 이는 성능 저하의 원인이 될 수 있습니다.
이 곳에서는 Draw Call이 발생하는 이유와 최적화 방법, 그리고 Draw Call 발생 시 CPU의 비용이 왜 발생하는지를 중심으로 설명할 예정입니다.
Draw Call 은 왜 발생하는 가?
위에서 언급했듯, Draw Call 은 CPU → GPU에게 어떤 것을 그리라 하는 과정입니다.
유니티 게임 씬에서는 다양한 오브젝트가 존재합니다. 각각의 요소가 화면에 그려지기 위해서는 개별적인 드로우콜이 필요합니다.
여기서 말하는 개발적인 드로우콜은 최적화를 하지 않았을 때를 기준으로 합니다.
Draw Call이 갖고 있는 정보
1.
렌더링할 메시(Mesh) 정보 : 드로우콜은 어떤 메시를 그릴지에 대한 정보를 포함합니다. 이는 오브젝트의 형태와 구조를 결정합니다.
2.
사용할 텍스처 정보 : 드로우콜은 오브젝트에 적용할 텍스처 정보를 지시합니다. 텍스처는 오브젝트의 표면에 적용되는 이미지나 패턴입니다.
3.
셰이더 및 렌더링 설정 : 셰이더는 오브젝트가 어떻게 빛을 반사하고 보이게 할지 결정합니다. 드로우콜은 사용할 셰이더와 관련 렌더링 설정(예: 블렌딩 모드, 깊이 테스트 등)을 포함합니다.
4.
변환 정보 : 오브젝트의 위치, 회전, 크기 등의 변환 정보도 드로우콜에 포함됩니다.
Draw Call 은 왜 비용이 큰가?
기본 적으로 Draw Call 하나당 렌더링 파이프라인 과정이 한 번 실행됩니다.
Draw Call을 줄이는 것은 렌더링 파이프 라인 과정을 제거한다는 의미입니다. 즉, GPU의 과정을 완전히 생략하는 것입니다.
CPU에서의 Draw Call 비용은 다음과 같이 발생합니다.
1. 상태 변경(State Changes)
•
드로우콜을 수행할 때마다, GPU는 렌더링을 시작하기 전에 현재의 렌더링 상태(예: 사용할 셰이더, 텍스처, 렌더링 파라미터 등)를 설정해야 합니다. 이러한 상태 변경은 비용이 많이 드는 작업일 수 있으며, 많은 계산 리소스를 요구합니다.
◦
설정 변경의 복잡성 : 각 상태 변경은 GPU에 전달되기 전에 CPU에서 처리되어야 합니다. CPU는 적절한 명령을 생성하고, 필요한 데이터를 준비하여 GPU로 전송하는 작업을 수행합니다.
2. 자원 바인딩(Resource Binding)
•
각 드로우콜에는 특정 메시, 텍스처, 셰이더 등과 같은 그래픽 리소스를 GPU에 바인딩하는 과정이 포함됩니다. 이러한 바인딩 과정도 CPU 리소스를 사용합니다.
3. 명령 버퍼링(Command Buffering)
•
CPU는 GPU에 전송할 명령을 버퍼에 쌓아두고, 적절한 시점에 이를 GPU로 전송합니다. 명령을 버퍼링하고, 관리하고, 전송하는 과정 역시 CPU 작업 부하를 증가시킵니다.
4. 드라이버 오버헤드(Driver Overhead)
•
GPU에 명령을 내리기 위해서는 운영 체제와 GPU 드라이버를 통해야 합니다. 드라이버는 이러한 명령을 처리하고, 최적화하며, GPU에 적절한 형식으로 전달하는 역할을 합니다. 이 과정에서 발생하는 드라이버 오버헤드도 CPU 작업 부하를 증가시킵니다.
Draw Call 을 최적화 하는 과정
기본적인 유니티 최적화 기법은 다음과 같습니다.
그러나 실제 게임 개발에서는 위의 최적화 기법뿐만 아니라 다양한 기법을 사용하여 최적화를 진행합니다.
예를 들어, 탑뷰 게임에서는 불필요한 외부 3D 오브젝트들을 하나의 2D 스프라이트로 만들어 관리하는 기법이 사용됩니다.