본문 바로가기
게임 개발 일지/내일배움캠프 TIL

[Unity] 드로우콜 (Draw Call)

by 빛하_ 2024. 2. 26.

게임에 기능을 모두 넣고 종료 시점까지 한 사이클을 굴렸다면, 최적화라는 과제가 남는다.

게임 개발에서 최적화를 공부할 때 반드시 등장하는 것이 드로우콜과 배칭이다.

드로우 콜(Draw Call)

드로우콜이란 CPU가 GPU에게 오브젝트를 그리라고 명령하는 것을 의미한다. 

 

 

GPU는 CPU에 의해서 처리되고 GPU가 Mesh를 렌더링 할 때 지오메트리 데이터를 읽어오는 공간이 바로 GPU Memory이다. 따라서 Mesh를 그리기 위해서는 GPU Memory에 Mesh 관련 정보가 있어야 한다.

GPU는 CPU Memory에 접근할 수 없기 때문에 GPU Memory에 데이터를 다시 복사한다. 이 과정을 거쳐 GPU Memory에는 메쉬 정보가 저장된다. GPU는 그릴 대상에 대한 상태 정보를 담는 테이블이 있는데 이 테이블을 렌더 상태 테이블이라고 한다. 렌더 상태 테이블에는 버텍스, 메쉬, 쉐이더 등의 상태 정보가 담겨 있다.

이 상태 정보를 CPU는 GPU에게 전달하고 GPU는 렌더 상태 정보를 저장한다. 마지막으로 CPU는 GPU에게 그리라고 명령하는데 이를 DP Call이라고 한다. 또한 CPU는 GPU에게 바로 명령을 하지 않고 Command 버퍼라는 곳에 명령 버퍼를 저장한다. 그러면 GPU는 할 일을 처리한 후에 Command 버퍼에서 명령을 순차적으로 가져가서 수행한다. (이때 FIFO 구조로 데이터를 불러온다)

 

CPU와 GPU의 상호작용

CPU에서 GPU에 명령하기

  • 일반적으로 CPU에서 렌더링, 상태 변경 등의 명령을 GPU에 전달한다.
  • 그런데 GPU가 바쁘게 작업하는 도중이라면, CPU는 GPU의 작업이 끝나기를 하염없이 기다리게 될 수 있다.
  • 따라서 커맨드 패턴(Command Pattern)과 메시지 큐(Message Queue)에 의한 비동기 방식을 활용한다.
  • CPU에서 GPU에 전달할 명령(Command)을 임시 공간에 담아 두고, GPU가 여유 될 때 명령을 하나씩 꺼내어 처리한다.

Command Buffer(커맨드 버퍼)

  • CPU의 각 스레드에서는 GPU에 전달할 렌더링 관련 명령을 모듈화하여 커맨드 버퍼에 차곡차곡 쌓아 임시로 저장한다.
  • 그리고 GPU의 공유 커맨드 큐에 전송한 뒤, GPU를 기다리지 않고 다른 작업을 수행할 수 있다.
  • 각 스레드마다 커맨드 버퍼를 갖고 공유 큐에 전송할 수 있으므로, 멀티스레드를 활용한 병렬 처리에도 용이한 방식이다.
  • 명령을 곧장 커맨드 큐에 전송하는 것은 데이터 동기화 문제로 인한 성능 저하를 유발할 수 있으므로, 명령을 모아 버퍼 단위로 전송하는 방식을 사용하는 것이다.

Command Queue(커맨드 큐)

  • GPU에는 CPU와 GPU가 함께 공유하는 커맨드 큐가 존재한다.
  • GPU는 여유가 될 때마다 커맨드 큐에 담긴 커맨드 버퍼를 차례로 꺼내어, 그 안에 담긴 명령들을 처리한다.

 

렌더 상태

 

Render States(렌더 상태)

  • GPU가 렌더링을 수행하기 위해 필요한 정보들
  • 쉐이더, 메시, 텍스쳐, 알파 블렌딩 옵션, ZTest 및 스텐실 옵션 등이 있다.

Render State Changes(렌더 상태 변경)

  • GPU에서 렌더링할 대상의 상태가 변경될 경우 수행된다.
  • CPU가 GPU에 렌더 상태 정보를 전송하며 상태 변경 명령을 보낸다.

 

드로우콜의 구성요소

 

SetPass Call

  • 쉐이더로 인한 렌더 상태 변경만을 의미한다.
  • 쉐이더 내의 Pass 변경, 쉐이더(Material) 자체의 변경, 쉐이더 내 파라미터들의 변경에 해당된다.
  • 메시의 변경은 렌더 상태 변경이지만, SetPass Call에는 해당되지 않는다.
  • 따라서 메시가 달라도 Material이 같다면 SetPass Call은 딱 1번만 발생한다.

DP Call(Draw Primitive Call)

  • CPU가 GPU에 그리라는 명령을 직접적으로 호출하는 것(예 : glDrawElement())
  • 그려야할 대상의 정보가 조금이라도 달라지는 경우, DP Call에 앞서 렌더 상태 변경이 동반된다.
  • GPU는 현재 렌더 상태 정보를 기반으로 렌더링을 수행한다.

Draw Call

  • CPU에서 GPU에 렌더링 명령을 전송하는 것
  • Render State Changes + DP Call 과정을 통칭한다.

 

 

 

 

댓글