자가라 노트

Unity

[Unity]Rendering 렌더링

자가라o 2021. 6. 30. 06:01

렌더링 과정

GPU가 메시를 렌더링 하려면 GPU메모리에서 테이터를 읽어올 수 있어야 한다.

로딩시점에 데이터를 메모리에 올려놓고 씬전환 시점등에서 데이터를 해제.

게임중에는 데이터가 상시 메모리에 상주해야 한다.

텍스쳐 쉐이더등 렌더링에 필요한 데이터 모두 GPU 메모리에 존재해야한다.

 

렌더링 수행전 데이터 로딩 (메시정보를 GPU 메모리에 저장)

CPU가 스토리지(HDD, SDD, SD등)에서 파일을 읽어들이고 데이터를 파싱 CPU 메모리에 데이터를 올린다.

CPU메모리의 데이터를 GPU메모리로 복사


렌더링

렌더링 루프중 렌더링을 해야하는 시점이 오면 데이터(GPU에 텍스쳐, 버텍스, 쉐이더등)를 순서대로 전달해 줘야하는데 GPU에는 해당 정보들을 담는 테이블, Render State(렌더상태)를 가지고 있다. 렌더상태의 테이블에는 필요데이터의 주소를 가지고있다.

CPU가 렌더상태를 변경하는 명령을 보내면, GPU는 렌더상태에다가 오브젝트를 그리기 위한 정보를 저장한다.

CPU는 명령을 보내고 마지막에 GPU에게 메시를 그리라는 명령을 보내는데 이것을 Draw Primitive Call, DP Call이라고  한다.

GPU는 DP Call을 받으면 렌더상태의 정보를 기반으로 메시를 렌더링 한다.

메시를 렌더링 한후 CPU는 또 다른 오브젝트를 렌더링 하기위해 상태 정보 변경 여부에 따라 변경하라는 명령을 보내거나 보내지 않는다.

반복.

Draw Call = (상태 변경 + Draw Primitive call)


Command Buffer

사실 CPU가 GPU에게 명령을 줄때 중간에 한단계가 더 있다.

CPU가 GPU에게 직접 명령을 전달한다면 GPU의 작업이 끝나지 않았을때 무기한 기다려야 할수도있다.

그래서 CPU가 GPU사이에는 Command Buffer라는 버퍼가 하나 있는데, CPU는 버퍼에 명령을 쌓아놓고 GPU는 작업이 처리되는 대로 버퍼에서 새로운 명령을 가져다 실행한다. 버퍼는 FIFO방식으로 명령을 처리한다


// Vulkan과 Metal은 여러개의 커맨드버퍼를 이용해 멀티쓰레드로 처리하기도 한다. 따라서 기존 OpenGL ES보다 드로우콜 부담이 적다.

 

// 또 CPU의 명령은 GPU에서 사용하는 신호로 변환되어야 하는데 이는 CPU의 몫으로 이때 오버헤드가 발생하기 때문에 드로우콜은 CPU의 오버헤드라고 한다.

 

// Multithreaded Rendering 멀티쓰레드 렌더링

렌더링에 필요한 작업들을 별도의 쓰레드로 분리해서 렌더링 성능을 높여 CPU의 부담을 줄여준다.

구형디바이스나 CPU코어가 적을때는 잘 돌아가지 않을 수 있다.

드로우콜 병목이 아닐때는 딱히 영향을 주지 못함


드로우콜은 GPU의 성능보다 CPU의 성능에 의존적이다.

따라서 드로우콜로 인한 성능 하락을 줄이려면(텍스처나 폴리곤 수를 줄이는게 아니고) 드로우콜 횟수를 줄여야 한다.