336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

"모바일 기기의 Tile Based Rendering(타일 기반 렌더링)과 유니티에서의 주의 사항 #1 : TBR의 이해"에서 이어지는 글입니다. 


앞선 글에서 설명드린 바와 같이 모바일에서는 타일 단위로 쪼개서 렌더링하는 방식을 사합니다. 그러다보니 전통적인 렌더링 방식에서와는 조금 다른 주의 사항이 몇 가지 존재합니다. 


알파블렌딩(Alpha Blending) VS 알파테스트(Alpha Test)

전통적으로 데스크톱 게임의 리소스에는 알파블렌딩보다 알파테스트의 사용이 권장되어왔습니다. 불투명한 철망이라든가 찢어진 옷감같은 경우는 불투명하기때문에 비싼 블렌딩 연산을 사용하기보다는 알파테스트를 사용함으로써 픽셀 연산도 절약하자는 의도였습니다. 하지만 모바일의 TBR(Tile Based Rendering, 타일 기반 렌더링)에서는 정반대로 알파테스트보다는 알파블렌딩의 사용이 권장됩니다. 

알파테스트처리를 하기 위해서는 픽셀쉐이더에서 동적분기(if문)가 사용됩니다. 데스크톱에서는 쉐이더의 동적 분기가 고속으로 처리되지만, 모바일에서는 동적 분기 성능이 취약합니다. 때문에 알파테스트는 쉐이더의 성능윽 하락시키는 원인이 됩니다.

게다가, TBDR(Tile Based Deferred Rendering, 타일 기반 지연 렌더링)에서는 픽셀 차폐의 고속 처리를 깨트립니다. 앞서 언급했다시피 TBDR에서는 여러 드로우콜의 버텍스 쉐이더 결과를 모아두었다가 은면 제거(Hidden Surface Removal)를 거친 뒤 실제 보이는 픽셀만 처리합니다. 하지만 이는 알파테스트를 사용하지 않는 완전한 불투명메시일 경우에만 해당됩니다. 알파테스트를 사용하면 버텍스 처리 단계에서는 해당 폴리곤이 차폐 되는지의 여부를 판단할 수 없기때문에 Deferred 처리를 깨트릴 수 밖에 없게됩니다.

유니티에서는 이를 방지하기위해서 완전 불투명 오브젝트들을 모두 렌더링처리한 후에 알파테스트 오브젝트들을 렌더링합니다. 따라서 알파 테스트를 제한적으로만 사용한다면 그렇게 치명적이지는 않습니다. 하지만 애초에 TBDR 칩셋의 구조가 알파테스트 처리에 적합하지 않기 때문에 알파테스트를 사용하지 않는 것이 좋습니다. 그런 이유로, 유니티의 내장 쉐이더 중 Mobile 카테고리에는 알파 테스트 쉐이더가 존재하지 않습니다.

반면에, 알파블렌딩은 데스크톱에 비해서 고속으로 처리가됩니다. 알파블렌딩과정은 출력 내부적으로 대상 버퍼의 읽기/쓰기가 발생합니다. 데스크톱에서는 DRAM에 존재하는 프레임버퍼 전체에 접근해야하기때문에 높은 대역폭을 잡아먹게됩니다. 하지만 TBR에서는 이 처리가 타일 단위로 이루어지고 칩 내부에 존재하는 메모리에서 이루어지므로 고속으로 처리됩니다.


오버드로우

다만 명심해야 할 것은 알파 블렌딩 처리 자체가 빠르다는 것일 뿐이지 오버드로우에서 자유로와진다는 것은 아닙니다. 예를 들어서 넓은 영역의 파티클을 높은 밀도로 뿌리는 것은 여전히 오버드로우 문제를 일으켜서 성능 저하로 직결됩니다. 모바일은 쉐이더 성능이 기종에 따라 천차만별이므로 오버드로우로 인해서 쉐이더 싸이클이 낭비되는 것은 치명적인 문제가 됩니다. 웬만하면 불투명 오브젝트 위주로 리소스를 만들기를 권장합니다. 알파 블렌딩 오브젝트 또는 파티클은 오버드로우를 최대한 피해서 사용하시기를 권장합니다.


로우 폴리곤

너무나 당연한 이야기라 뜬금없어 보일수도 있겠지만 많은 폴리곤을 처리하면 성능이 하락합니다. 게다가, TBDR에서는 많은 폴리곤 처리의 부담이 더욱 큽니다. 앞서 설명드린 버텍스 쉐이더의 결과물들을 담아두는 파라미터 버퍼(Parameter Buffer)의 크기는 당연하게도 무한하지 않습니다. 따라서 이 버퍼가 넘쳐버리면 더 이상의 버텍스 쉐이더 결과물을 받아들이지 못하고 버퍼를 비워줘야합니다. 이 버퍼를 비워주기 위해서는 타일의 픽셀 처리 후 프레임버퍼로 출력하는 사이클을 거쳐야합니다. 때문에, 이론상으로는 TBDR에서는 픽셀의 오버드로우가 발생하지 않아야하지만, 현실적으로는 폴리곤이 많을수록 오버드로우가 발생하게 발생하게 됩니다. 그러므로 오브젝트의 렌더링 퀄리티를 높여야한다면 버텍스를 늘리는 것 보다는 픽셀쪽 연산을 늘리는 것이 오히려 이득일 수도 있습니다.


렌더 텍스쳐(Render Texture)

렌더 텍스쳐를 사용하면 유니티 내부적으로 렌더 타겟(Render Target)을 변경하는 행위를 거치게됩니다. 이러한 렌더타겟을 변경하는 행위는 데스크톱에서도 성능을 잡아먹는 행위가 됩니다. 렌더 타겟을 바꾸기위해서는 CPU가 GPU를 대기하는 과정을 거치게되면서 CPU와 GPU의 병렬 관계가 잠기 깨지는 현상이 발생하기 때문입니다. 

게다가, TBDR에서는 더욱 치명적인 행위가 됩니다. 렌더 타겟을 변경할 시에는 현재 파라미터 버퍼에 쌓여있는 데이터들을 모두 처리해주고 프레임버퍼에 출력합니다. 그 후 다음 렌더 타겟을 위해서 파라미터 버퍼를 비워줍니다. 이런식으로 렌더 타겟을 바꿀 시 deferred 사이클을 추가적으로 처리해줘야 합니다. 때문에 유니티의 카메라에서 타겟 텍스쳐(Target Texture)로 렌더 텍스쳐를 사용하는 경우에는 TBDR의 효율이 떨어지게 됩니다.

이미지 후처리 효과(Image post process Effect)

최근 디바이스들은 컬러 그레이딩이나 블룸 효과 등 이미지 후처리들을 사용할 수 있을 만큼 성능이 좋아졌습니다. 하지만 이러한 이미지 후처리들을 너무 남발해서 사용하면 안되고 필요한 것만 선택적으로 사용해야 합니다. 

우선, 이미지 후처리들은 내부적으로 렌더 타겟을 변경하는 행위를 합니다. 하지만, 더 큰 문제는 대역폭입니다.  물론 픽셀 처리 능력도 관건이지만 대역폭이 더욱 큰 문제가 됩니다. 이미지 후처리들은 현재 렌더링 한 결과를 담고있는 렌더 타겟을 픽셀쉐이더의 입력 텍스쳐로 가져옵니다. 이 때 입력받는 텍스쳐는 칩 내부에 있는 타일이 아니라 공용 메모리에 있는 렌더 타겟을 가져오기때문에 엄청난 대역폭을 잡아먹게 됩니다. (예 : 1080p) 그러므로 이미지 후처리는 신중하게 사용해야 합니다.


카메라 클리어(Clear)

예전의 데스크톱 그래픽카드에서는 한 프레임의 렌더링을 시작하기 전 일부러 화면을 클리어해주지 않고 렌더링을 시작하는 경우도 있었습니다. 하지만 현대의 데스크톱 그래픽카드에서는 반드시 클리어를 해주어야만 하드웨어의 고속 처리를 지원받을 수 있습니다. 이는 모바일 기기의 TBR에서도 마찬가지입니다. 클리어를 수행하여 칩 내부의 버퍼들을 비워줘야만 이후 렌더링 과정을 고속으로 처리할 수 있습니다. 따라서, 유니티의 카메라에서 Clear Flag를 Don’t clear로 두는 것은 데스크톱에서나 모바일에서나 웬만해서는 권장되지 않습니다. 


MSAA

데스크톱에서는 MSAA가 매우 큰 부담이 됩니다. 역시 마찬가지로 대역폭이 가장 큰 원인입니다. 예를 들어 1080p해상도의 화면을 MSAA 2X로 처리하려면 2160p만큼의 대역폭이 필요해집니다. DRAM으로부터 그만큼의 대역폭을 요구한 다는 것은 매우 큰 부담이 되는것입니다. 하지만 TBR에서는 이 역시 칩 내부의 타일에서 이루어집니다. 16x16 혹은 32x32정도에 불과한 타일로 MSAA처리해주는 것은 그리 부담이 되지 않습니다. 

유니티에서 MSAA를 사용하기위해서는 퀄리티 셋팅에서 Anti Aliasing을 2 혹은 4로 선택해주면 됩니다. 다만 개인적으로는, 매우 높은 DPI를 자랑하는 대부분의 모바일 기기에서 안티 앨리어싱이 굳이 필요할 지는 모르겠습니다 :)


프로파일링

유니티5부터 프레임 디버거(Frame Debugger)가 추가되어서 프레임 별 렌더링 과정을 디버깅해볼 수 있게 되었습니다. 이를 통해서 오브젝트의 렌더링 과정이나 배칭 현황을 손쉽게 확인 해 볼 수 있게 되었습니다.  

이미지 출처 : http://docs.unity3d.com/Manual/FrameDebugger.html

하지만 애석하게도 유니티의 프레임 디버거만으로는 드로우콜 별 GPU 퍼포먼스나 세부 상태를 확인하기는 힘듭니다. 다행히도, 칩셋 벤더마다 렌더링 과정을 세부적으로 프로파일링을 해볼 수 있는 툴을 제공해주고 있습니다. 아드레노 칩셋은 아드레노 프로파일러를 통해서, 말리 칩셋은 말리 프로파일러나 DS-5를 통해서, 아이폰은 XCODE를 통해서 프로파일링을 해볼 수 있습니다.

이미지 출처 : http://www.slideshare.net/ozlael/graphics-opt-ndc

다만 문제가 하나 있습니다. TBR 방식을 사용하는 칩셋은 콜 별 설능을 확인하는데 어려움이 없습니다. 하지만 TBDR 방식을 사용하는 칩셋은 콜 별 성능을 직관적으로 확인하는게 사실상 불가능하다는 것입니다. TBDR은 앞서 언급했다시피, 드로우콜 발생 시 픽셀 쉐이더를 즉시 처리하는 것이 아니라 파라미터 버퍼에 결과를 담아둡니다. 그 후 모든 드로우콜을 마치고 나면 그때서야 실제 렌더링을 수행하기 때문에 콜 별 성능을 실질적으로 확인해 볼 수가 없는 것입니다. 따라서 X-code에서 아이폰의 렌더링을 프로파일링 해보면 성능 관련 숫자가 0으로 나오게 됩니다. 0이 아닌 숫자가 나오는 경우도 있지만 이 역시 신뢰할 수 없는 숫자입니다. 대신 프레임 전체에 걸린 성능을 확인해보거나 콜 당시의 사용 텍스쳐 등 주변 정보로 유추해보는 수 밖에 없습니다. 이처럼 아이폰의 프로파일링은 좀 까다로운 편입니다.

이미지 출처 : http://www.slideshare.net/ozlael/graphics-opt-ndc


화면 변화율

TBR에서는 렌더링을 칩 내부의 타일에다 하는 과정은 대역폭을 먹지 않지만, DRAM 영역에 존재하는 프레임 버퍼에 타일을 출력하는 과정에서는 어느 정도는 대역폭이 필요할 수 밖에 없게됩니다. 이러한 대역폭을 조금이나마 절약하기 위해서 말리에서는 트랜잭션 엘리미네이션(Transaction Elimination)이라는 기술을 사용합니다. 타일 별로, 이전 프레임과 화면 결과가 달라지지 않은 타일의 영역은 프레임버퍼를 갱신하지 않고 이전 프레임의 결과를 재활용 하는 것입니다. 그렇게 하면 칩 내부 메모리에서 시스템 메모리로 복사하는 양이 줄어드는 효과를 갖게됩니다. 아래 예시 이미지의 파란 글자 타일이 바로 그 부분에 해당합니다. 

이미지 출처 : http://community.arm.com/

따라서, 고정 카메라를 사용한다면 스카이박스 등의 배경에는 최대한 변화를 피하는 것도 좋은 방법이 될 수도 있습니다. 현실적으로는 3D 게임에는 이러한 조건에 해당하는 경우가 많지는 않을 것입니다. 하지만 2D 게임에는 적합하는 부분이 많은 것입니다.


마치며

TBR에 관한 내용이랑 TBDR에 관한 내용을 같이 언급하긴 하였습니다. 하지만 대부분은 아이폰이나 안드로이드폰만 타겟으로 설정하고 개발할 것이고, 플랫폼마다 데이터를 별도로 제작하지는 않을 것이라 예상합니다. 따라서 현실적으로는 TBR, TBDR 모두 고려대상으로 삼고 이러한 사항들을 인지하면서 개발하여야 할 것이라 생각합니다.

감사합니다.


Posted by ozlael
,