원문 : https://community.arm.com/developer/tools-software/graphics/b/blog/posts/the-mali-gpu-an-abstract-machine-part-2---tile-based-rendering

주의 : 번역이 개판이므로 이상하면 원문을 참고하세요.

주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.


이전 블로그에서 추상 머신을 정의하기 시작했으며, 그것은 Mali GPU 와 드라이버의 애플리케이션 단에서 볼 수 있는 동작들에 대해서 기술하는 데 사용될 수 있습니다. 이 머신의 목적은 개발자들에게 OpenGL ES API 의 기저에 깔린 흥미로운 동작들에 대한 멘탈 모델을 제공하는 것입니다. 이 모델은 애플리케이션의 성능에 영향을 주는 이슈들을 설명하는 데도 사용될 수 있습니다. 필자는 이 시리즈의 뒤쪽 블로그에서 이 모델을 사용해 개발자가 그래픽스 애플리케이션을 개발하는 동안 만날 수 있는 일반적인 성능 함정( pot-hole )들에 대해서 살펴 볼 것입니다.

이 블로그는 계속해서 추상 머신의 개발에 대해서 이야기하며, Mali GPU 패밀리의 타일 기반 렌더링에 대해 살펴 볼 것입니다. 여러분이 파이프라인에 관한 첫 번째 블로그를 읽어다고 가정합니다. 만약 읽지 않았다면 먼저 읽고 오시기 바랍니다.

The "Traditional" Approach

메인전원에 의해 전력을 공급받는 전통적인 데스크탑 GPU 아키텍쳐 -- 일반적으로 즉시 모드 아키텍쳐( immediate mode architecture )라 불립니다 -- 에서는 프래그먼트 셰이더( fragment shader )들이 각 드로 콜( draw call )에서 순차적으로 각 프리미티브( primitive ) 상에서 수행됩니다. 각 프리미티브들은 다음 프리미티브를 시작하기 전에 완료되기 위해 렌더링되는데, 대충 다음과 같은 알고리즘을 사용합니다:

스트림 내의 어떤 삼각형은 화면 내의 일부 영역을 덮고 있기 때문에, 이들 렌더러에 의해서 유지되는 데이터 워킹 셋( working set of data )은 큽니다; 일반적으로는 적어도 전체 화면 크기의 컬러 버퍼( color buffer ), 뎁스( depth ) 버퍼, 그리고 스텐실( stencil ) 버퍼. 최신 장치들을 위한 일반적인 워킹 셋은 픽셀당 32 비트 컬러 버퍼, 그리고 32 비트로 패킹된( packed ) 뎁스/스텐실 버퍼입니다. 그러므로 1080p 디스플레이는 16 MB 의 워킹 셋을 가지며, 4k2k TV 는 64 MB 의 워킹 셋을 가집니다. 그것들의 크기 때문에, 이 워킹 버퍼들은 반드시 칩 바깥에 있는 DRAM 에 저장되어야 합니다.

모든 블렌딩( blending ), 뎁스 테스트, 스텐실 테스트 연산은 현재 프래그먼트의 픽셀 좌표를 위한 현재 데이터 값을 요구합니다. 이 값들은 이 워킹 셋으로부터 획득( fetch ) 니다. 셰이딩된 모든 프래그먼트들은 일반적으로 이 워킹 셋을 손대게 되며, 그래서 고해상도에서는 프래그먼트에 대해 읽기-수정-쓰기 연산을 하게 되면, 캐싱이 다소 완화해 준다고 하더라도, 이 메모리 상에서 예외적으로 높은 대역폭을 소비할 수 있습니다. 또한 높은 대역폭 접근에 대한 요구는 매우 많은 핀과 특별한 고주파수 메모리를 가진 넓은 메모리 인터페이스를 요구합니다. 둘 다 외부 메모리 접근을 필요로 하며, 이는 특히 에너지를 많이 사용하는 작업입니다.

The Mali Approach

Mali GPU 패밀리는 매우 다른 접근 방법을 사용하는데, 일반적으로 타일 기반 렌더링이라 불리며, 렌더링 동안 필요한 외부 메모리 접근과 전력( power ) 소비량을 최소화하기 위해서 설계되었습니다. 이 시리즈의 첫 번째 블로그에서 설명했듯이, Mali 는 각 렌더 타깃에 대해 구별되는 두 개의 패스 렌더링 알고리즘을 사용합니다. 그것은 먼저 지오메트리 처리를 모두 실행한 다음에 프래그먼트 처리를 실행합니다. 지오메트리 처리 스테이지 동안, Mali GPU 는 화면을 작은 16x16 픽셀 타일들로 쪼개고, 렌더링 중인 프리미티브들이 어떤 타일에 제출되고 있는지에 대한 리스트를 만듭니다. GPU 프래그먼트 셰이딩 단계가 실행될 때, 각 셰이더 코어는 한 번에 하나의 16x16 픽셀 타일을 처리합니다. 다음 타일을 렌더링하기 전에 렌더링이 끝납니다. 타일 기반 아키텍쳐에서 알고리즘은 다음과 같은 식입니다:

16x16 픽셀 타일은 전체 화면 영역에 비해 작은 조각이므로, GPU 셰이더 코어와 강하게 결합되어 있는 빠른 RAM 에 전체 타일을 위한 전체 워킹 셋( 컬러, 뎁스, 스텐실 )을 유지하는 것이 가능합니다.

이 타일 기반 접근 방법은 여러 개의 이점을 가지고 있습니다. 그것들은 거의 개발자들에게 있어 투명하지만( transparent ) 알아 두면 가치가 있습니다. 특히 여러분의 칸텐트가 가지는 대역폭 비용을 이해하려고 할 때 그렇습니다:

  • 워킹 셋에 대한 모든 접근들은 지역적( local ) 접근입니다. 그것은 빠르면서 전력을 덜 소비합니다. 외부 DRAM 에 대한 읽기나 쓰기에 필요한 전력은 시스템 설계에 따라 다양해지지만, 1 Gbyte/s 의 대역폭을 위해 120 mW 정도는 쉽게 소비됩니다. 내부 메모리 접근들은 대략 이 보다는 자리수가 다르게 낮습니다. 그러므로 이것이 매우 중요하다는 것을 이해할 수 있을 겁니다.
  • 블렌딩은 빠르고 전력 효율이 높습니다. 왜냐하면 블렌드 연산들을 위해 요구되는 대상 컬러 데이터를 손쉽게 이용할 수 있기 때문입니다.
  • 타일은 4x, 8x, 16x 멀티샘플 안티에일리어싱( multisample antialiasing ) 을 허용하기 위해 타일 메모리에 충분한 샘플들을 저장할 수 있을만큼 충분합니다. 이는 고품질이며 부하가 적은 안티 에일리어싱을 제공합니다. 하지만 관련 작업 셋의 크기 때문에 ( 일반적인 단일 샘플링 렌더 타깃의 4, 8, 16 배; 4k2k 디스플레이 패널의 16x MSAA 에는 1 GB 의 워킹 셋 데이터가 필요합니다 ), 개발자에게 MSAA 를 기능으로 제공하는 즉시 모드 렌더러는 드뭅니다. 왜냐하면 일반적으로 외부 메모리 공간과 대역폭이 너무 비싸기 때문입니다.
  • Mali 는 타일 작업의 끝에서 메모리에다가 단일 타일을 위한 컬러 버퍼만을 써야만 합니다. 이 시점에 우리는 그것의 최종 상태를 알게 됩니다. CRC 체크를 통해 메인 메모리에 있는 현재 데이터와 블록의 컬러를 비교할 수 있습니다 -- Transaction Elimination 이라 불리는 처리입니다 -- 이때 타일 칸텐츠가 동일하다면 쓰기를 취소하며 SoC 의 전력을 절약하게 됩니다. 필자의 동료인 tomolson 은 이 기술에 대한 훌륭한 블로그를 작성했습니다. 그는 Transaction Elimination( Angry Birds 라 불리는 어떤 게임에서 이것에 대해 들어 봤을 겁니다 )에 실제 예제를 완성했습니다. 필자는 Tom 의 블로그에서 이 기술을 더욱 자세하게 설명할 것입니다만, 여기에서는 그 기술에 대해서 살짝 훔쳐 보기만 하겠습니다( "extra pink" 타일들만이 GPU 에 의해 쓰여진 것입니다 - 다른 것들은 성공적으로 취소된 것입니다 ).
  • 빠르고, 손실없는 압축 기법을 사용해서 Transaction Elimination 을 실행하는 타일을 위해 컬러 데이터를 압축할 수 있습니다 -- ARM Frame Buffer Compression( AFBC ) -- 이는 대역폭과 전력을 더 줄여 줍니다. 이 압축은 오프스크린 FBO 렌더 타깃들에 대해서 수행될 수 있으며, 그것은 GPU 에 의해 일련의 렌더링 패스들에 텍스쳐로서 읽어들여질 수 있습니다. 또한 거기에 공급되는 메인 윈도우 서피스는 시스템의 Mali-DP500 과 같은 AFBC 호환 디스플레이 컨트롤러입니다.
  • 대부분의 칸텐트는 뎁스 버퍼와 스텐실 버퍼를 가지고 있습니다. 하지만 그것들의 칸텐츠는 일단 프레임 렌더링이 끝낙 나면 유지될 필요가 없습니다. 만약 개발자가 Mali 드라이버에 뎁스 버퍼와 스텐실 버퍼를 유지할 필요가 없다고 알리면 -- 이상적으로는 glDiscardFramebufferEXT ( OpenGL ES 2.0 ) 이나 glInvalidateFramebuffer ( OpenGL ES 3.0 ) 에 대한 호출을 통해, 그리고 어떤 경우에는 드라이버에 의해서 추론될 수도 있지만 -- 타일의 뎁스 칸텐트와 스텐실 칸텐트는 결코 메인 메모리에 써지지 않을 것입니다. 대역폭과 전력을 크게 절약하는 또다른 방법입니다.

위의 리스트들을 통해 명확해 진 것은 타일 기반 렌더링이 여러 가지 이점을 가지고 있다는 것입니다. 특히 프레임버퍼 데이터와 관련한 대역폭과 전력에 있어서 매우 많이 절약해 주며, 저비용 안티 에일리어싱을 제공할 수 있습니다. 단점은 무엇일까요?

모든 타일 기반 구조의 필수적인 부하는 버텍스 셰이더에서 프래그먼트 셰이더로 넘어 가는 시점에 발생합니다. 지오메트리 처리 스테이지의 출력은 버텍스와 타일러 즉시 상태( tiler immediate state ), 반드시 메인 메모리에 쓰여진 후에 프래그먼트 처리 스테이지에서 다시 읽어들여져야 합니다. 그러므로 다양한 데이터와 타일러 상태를 위한 추가 대역폭을 소비하는 것과 프레임 버퍼 데이터를 위한 대역폭을 절약하는 것 사이에서 절충을 하기 위해 균형이 잡혀 있어야 합니다.

오늘날 현대의 소비자 가전제품은 높은 해상도 디스플레이로 이동하고 있습니다; 1080p 는 이제 스마트 폰에서 일반적이며, Google Nexus 10 의 Mali-T604 와 같은 태블릿은 WQXGA( 2560x1600 )에서 동작합니다. 4k2k 는 텔레비전에서는 새로운 "필수품( must have )"이 되고 있습니다. 화면 해상도와 프레임 버퍼 대역폭은 빠르게 커지고 있습니다. 이 영역에서 Mali 가 활약하고 있으며, 대부분 애플리케이션 개발자들에게 있어서는 투명하게 동작합니다 - 여러분은 이런 기능들을 애플리케이션을 변경하지 않고도 그냥 사용할 수 있습니다.

지오메트리 측면에서, Mali 는 복잡도에 잘 대응하고 있습니다. 많은 고사양 벤치마크들이 프레임 당 백만 개의 삼각형들을 사용하며, 이는 Android 앱 스토어에 있는 인기있는 게이밍 애플리케이션들과 비교하면 한 두 자리수 만큼 더 복잡도를 가지고 있습니다. 하지만 즉시 지오메트리 데이터는 메인 메모리에 접근하게 되므로, GPU 성능을 튜닝하고 시스템이 최선을 다하게 하는 데 적용될 수 있는 몇 가지 유용한 팁들과 트릭들이 있습니다. 그것들은 각각 블로그를 써도 될 만큼 가치가 있습니다. 그래서 우리는 이 시리즈의 뒷 부분에서 그것들에 대해 다룰 것입니다.

Summary

이 블로그에서 필자는 데스크탑 스타일 즉시 모드 렌더러와 Mali 에서 사용하는 타일 기반 접근 방법을, 특히 메모리 대역폭을 살펴 봄으로써, 비교하고 그것들의 차이점을 보여 주었습니다.

다음 시간에 튜닝을 하고 Mali 셰이더 코어 자체에 대한 간단한 블록 모델을 살펴 보면서 추상 머신에 대한 정의를 마칠 것입니다. Once we have that out of the way we can get on with the useful part of the series: putting this model to work and earning a living optimizing your applications running on Mali.

항상 댓글과 의견을 환영합니다.

Pete

+ Recent posts