Graphics/참고자료

[번역]Tile-Based Rendering

scahp 2020. 6. 25. 20:57

개인 공부용으로 번역한 거라 잘못 번역된 내용이 있을 수 있습니다.

또한 원작자의 동의 없이 올려서 언제든 글이 내려갈 수 있습니다.

출처 : https://developer.arm.com/solutions/graphics-and-gaming/developer-guides/learn-the-basics/tile-based-rendering/single-page

 

Overview

이 가이드는 타일기반 GPU 아키텍쳐의 장점과 단점을 소개합니다. 또한 Arm Mali 의 Tile-based GPU 아키텍쳐와 데스크탑 PC와 콘솔에서 사용하는 전통적인 Immediate mode GPU를 비교합니다.

Mali GPU는 tiled-based 렌더링 아키텍쳐를 사용합니다. 이것은 GPU가 타일이라 불리는 여러개의 작은 서브 영역으로 나뉘어진 출력 프레임버퍼에 렌더링 한다는 의미입니다. 그런다음 각 타일이 그것을 완료하면 메모리에 기록합니다. Mali GPU에서, 이런 tile은 작습니다, 각각 16x16 크기입니다.

이 가이드의 마지막에 당신은 immediate mode GPU와 tile-based GPU의 주요 이점과 과제를 이해하게 될 것입니다.

Immediate Mode GPUs

전통적인 데스크탑 GPU 아키텍쳐는 immediate mode 아키텍쳐로 알려져있습니다. immediate mode GPU는 매 드로우콜 마다 각각의 프리미티브가 차례로 버택스와 프래그먼트 쉐이더를 실행하면서 strict command stream으로 처리합니다.

 

이것은 병렬 처리와 파이프라이닝을 무시한 하이레벨 pseudo-code 예제 입니다:

python
for draw in renderPass:
    for primitive in draw:
        for vertex in primitive:
            execute_vertex_shader(vertex)
        if primitive not culled:
            for fragment in primitive:
                execute_fragment_shader(fragment)

아래의 다이어그램은 하드웨어 데이터 흐름과 메모리 상호작용을 보여줍니다:

 

 

 

 

Advantages

버택스 쉐이더의 결과, 그리고 그외 지오메트리 관련 쉐이더, 는 GPU 내부에 on-chip에 남아있을 수 있습니다. 이 쉐이더들의 결과는 파이프라인의 다음 스테이지가 데이터를 사용할 준비가 될때 까지 FIFO 버퍼에 저장될 수 있습니다. 이 의미는 GPU는 지오메트리의 중간 결과를 저장하고 가져오는 약간의 외부 메모리 대역을 사용할 수 있다는 것입니다.

Disadvantages

프래그먼트 쉐이딩은 각 드로우에서 삼각형의 위치에 따라 스크린 주변으로 점프합니다. 이것은 스트림의 특정 삼각형은 스크린의 특정 파트를 다루기 때문이며 삼각형들은 그리기 순서에 따라 처리되어집니다.
그 결과로 활성된 작업 세트는 전체 프레임 버퍼의 크기라는 의미합니다. 예를들어, 1440p 해상도를 생각해볼때, 컬러는 32 Bits-Per-Pixel (BPP), 그리고 packed depth/stencil은 32 BPP 를 사용합니다. 이것은 전체 작업 세트에 30MB이며, Chip에 유지하기에는 너무 큽니다 그래서 Off-chip 인 DRAM에 보관해야만 합니다.
GPU는 매 블랜딩, 깊이 테스트, 스텐실 연산 마다 이 작업세트로 부터 현재 프래그먼트의 픽셀에 대한 현재 데이터를 가져옵니다.
보통, 모든 쉐이딩 되는 프래그먼트들이 이 작업세트에 접근합니다. 그러므로 높은 해상도에서 이 메모리에 위치한 대역폭 로드는 아주 높을 수 있습니다. 각 프래그먼트 마다 읽기-수정-쓰기 연산을 여러번 하기 때문입니다. 그러나, 캐싱이 최근 접근한 프레임버퍼 부분을 GPU에 가까이 둬서 높은 대역폭 로드를 완화할 수 있습니다.

Tile-Based GPUs

Mali GPU는 렌더패스를 처리하기 위해 다른 접근법을 사용합니다, 그리고 이 접근법은 Tile-based rendering 이라고 부릅니다. 이 접근은 GPU가 프래그먼트를 쉐이딩 하는 동안 외부 메모리 접근을 최소화 합니다.
Tile-based 렌더는 화면을 작은 조각으로 나누고 메모리에 쓰기전에 프래그먼트 쉐이딩을 작은 타일마다 완료합니다. 이 작업을 하기 위해, GPU는 미리 지오메트리가 각 타일에 기여하는 것을 알아야만 합니다. 그러므로 tile-based 렌더러는 각 렌더 패스 처리를 2개로 나눕니다:

  • 첫 패스는 모든 지오메트리에 연관된 처리를 합니다, 그리고 어떤 프리미티브가 각 스크린타일에 기여하는지에 대한 타일 리스트를 데이터 구조를 생성합니다.
  • 두번째 패스는 모든 프래그먼트 프로세싱을 실행합니다, 타일별로, 그리고 그들이 완료했을때 타일을 다시 메모리에 씁니다. 주목할 점은 Mali GPU는 16x16 타일에 그린다는 것입니다.

여기에 tile-based 아키텍쳐를 위한 렌더링 알고리즘의 예가 있습니다:

python
# Pass one
for draw in renderPass:
    for primitive in draw:
        for vertex in primitive:
            execute_vertex_shader(vertex)
        if primitive not culled:
            append_tile_list(primitive)

# Pass two
for tile in renderPass:
    for primitive in tile:
        for fragment in primitive:
            execute_fragment_shader(fragment)

아래의 이미지는 하드웨어 데이터 흐름과 메모리와의 상호작용을 보여줍니다:

 

 

Advantage: Bandwidth

tile-based 렌더링의 주요 장점은 타일이 총 프레임버퍼의 작은 부분이라는 것입니다. 그러므로, 빠른 on-chip RAM으로 전체 컬러, 깊이 그리고 스텐실 작업 세트를 저장할 수 있습니다, 이것은 GPU shader core와 강하게 엮입니다.

 

깊이 테스트와 반투명 프래그먼트의 블랜딩을 위해 GPU가 필요한 프래그먼트 데이터는 그러므로 외부 메모리 접근없이 사용가능 합니다. Fragment-heavy 내용은 GPU가 프레임버퍼에 대한 공용 연산을 위해 필요한 외부 메모리 접근 회수를 줄이므로써 아주 큰 에너지 효율을 만들어 낼 수 있습니다.

 

또한 내용의 상당한 부분이 깊이와 스텐실 버퍼에 있습니다. 이것은 단지 쉐이딩 처리하는 동안에는만 일시적입니다. 만약 Mali drivers에게 당신이 Attachment가 보존될 필요가 없다고 해주면, 드라이버는 그들을 메인 메모리에 다시쓰지 않을 것입니다.

 

당신은 OpenGl ES 2.0에서 glDiscardFramebufferEXT, OpenGL ES 3.0의 glInvalidateFrameBuffer, 혹은 적절한 Vulkan의 적절한 렌더패스 storeOp 설정으로도 이것을 할 수 있습니다

 

더 많은 대역폭 최적화가 가능합니다. Mali GPU는 타일에 쓴 컬러 데이터를 렌더링이 완료된 때 메모리에 써야만 합니다, 그리고 이때 당신은 최종 상태를 압니다. 당신은 타일의 내용과 이미 메모리에 있는 현재 데이터를 Cyclic Redundancy Check(CRC) 체크로 비교할 수 있습니다. 이것은 "Transaction Elimination' 으로 불리는 프로세스를 실행합니다. 이 프로세스는 만약 컬러가 변경되지 않았으면, tile을 외부 메모리에 쓰는 것을 건너 뜁니다.

 

많은 경우, Transaction elimination 은 프래그먼트 쉐이더가 타일 내용을 만들고 있는 동안에는 성능에 도움을 주지 않습니다. 그러나, 이 프로세스는 UI 렌더링과 캐쥬얼 게이밍과 같은 많은 공통적인 use case에서 외부 메모리 대역폭을 줄여줍니다. 그 결과, 이것은 시스템 파워 소모도 줄여줍니다.

 

Mali GPU는 Arm Frame Buffer Compression(AFBC)라고 불리는 비손실 압축 구조를 사용하여 타일의 컬러데이터를 압축할 수 있습니다. 그리고 그것은 더 적은 대역폭과 파워 소비를 더욱 더 줄여줍니다.

 

주목할 점은 AFBC는 Render-to-texture 작업에 작동합니다. 그러나 윈도우 서피스의 압축은 AFBC가 활성화된 디스플레이 컨트롤러를 요구합니다. 그러므로 Framebuffer 압축은 대역폭을 몇배 절약합니다; GPU로 부터 기록될때나 매번 framebuffer를 읽을 때

 

Advantage: Algorithms

Tile-based 렌더러는 쓰지 않으면 계산량이 너무 비싸거나 대역폭이 너무 무거워지는 알고리즘 사용을 가능하게 해줍니다.

 

하나의 타일은 충분히 작습니다. 이 타일에 Mali GPU는 Multi-Sample-Anti-Aliasing(MSAA)을 가능하게 하기 위해 지역메모리에 충분한 샘플을 저장할 수 있습니다. 그 결과, 하드웨어는 분리된 resolve 패스 없이 타일을 외부 메모리로 writeback 하는 동안 여러개의 샘플들을 하나의 픽셀 컬러로 resolve 할 수 있습니다. Mali 아키텍쳐는 anti-aliasing을 할때, 아주 적은 성능 부하와 대역폭 비용을 허용합니다.

 

일부 고급기술은, 디퍼드 라이팅과 같은, 프래그먼트 쉐이더에서 프로그래밍 방식으로 이전 프레임 버퍼의 값에 접근하는 이득을 볼 수 있습니다.

 

전통적인 알고리즘은 디퍼드 라이팅 시 여러 픽셀 당 중간 값을 메인 메모리에 기록하는 Multiple Render Target(MRT) 렌더링으로 구현합니다, 그리고 다시 그들을 두번째 패스에 읽습니다.

 

Lowering Bandwidth Use

Tile-based 렌더러는 중간 픽셀 데이터가 타일 메모리로 부터 직접 공유되는 지점에서 적은 대역폭 접근을 가능하게 해줍니다, 그리고 GPU는 오직 최종적으로 라이팅 연산을 한 픽셀만 메모리에 씁니다.

 

디퍼드 쉐이딩의 G-Buffer에 대해, G-Buffer는 4개의 1080p 32bpp 중간 텍스쳐, 이 접근은 60 FPS에서 대역폭의 4GB/s 까지 절약 가능합니다.


아래의 확장은 OpenGL ES에서 이 기능을 노출시킵니다:

  • ARM_shader_framebuffer_fetch
  • ARM_shader_framebuffer_fetch_depth_stencil
  • EXT_shader_pixel_local_storage

불칸에서는, 병합가능한 서브패스가 이 기능에 접근 가능케 해줍니다.

Disadvantages

Tile-based 렌더링은 많은 이점을 가져다 줍니다, 특히 프레임버퍼 데이터와 연관된 대역폭의 큰 감소와 적은 비용의 안티 앨리어싱을 제공합니다. 그러나, 고려해야할 중요한 약점이 있습니다.

 

Tile-based 렌더링 구조의 주요 추가 부하는 지오메트리 패스에서 프래그먼트 패스의 전달하는 지점에서 적용 됩니다. GPU는 지오메트리 패스의 결과를 -- 버택스당 베어링(varying) 데이터와 tiler immediate state --프래그먼트 패스가 읽을 메인메모리에 저장합니다. 그러므로 지오메트리와 연관된 추가 대역폭 비용과 프레임버퍼 데이터의 대역폭 절약 비용을 맞춰야 합니다.

 

테셀레이선 같은, tile-based 아키텍쳐에서 불규칙적으로 몇몇 비싼 연산을 고려하는 것이 중요합니다. 이 연산들은 폭발적으로 증가한 지오메트리 데이터가 메인메모리에 다시 저장되기 보다 on-chip FIFO 버퍼 안에 저장 될 수 있는 immediate mode 아키텍쳐의 장점에 잘 맞게 디자인 되었습니다.

Next Steps

Tile-based GPU의 기반을 이해하는 것은 Arm Mali GPU와 함께 일하기 시작할 때 당신에게 도움을 줄 것입니다. 게다가 당신이 Mali 아키텍쳐에서 최고의 성능을 얻기 위해서 어떻게 당신의 그래픽스 작업흐름을 최적화 할지 고민하기 시작할때 tile-based 렌더러의 이점과 단점을 고려하는 것은 중요합니다.

반응형