GPU 아키텍처 (2) - 모바일 GPU와 TBDR - soo:bak
작성일 :
모바일 GPU의 대역폭 제약
이전 글에서 데스크톱 GPU의 구조와 렌더링 파이프라인을 다루었습니다.
데스크톱 GPU는 IMR(Immediate Mode Rendering) 방식으로 동작합니다. CPU가 드로우 콜을 제출하면, GPU는 즉시 렌더링 파이프라인 전체를 실행하여 프레임버퍼에 기록합니다.
텍스처, 버텍스/인덱스 버퍼, 프레임버퍼(컬러·깊이·스텐실) 등 렌더링에 필요한 데이터는 모두 GPU 코어 외부의 VRAM(Video RAM, 비디오 메모리) 에 위치합니다. 특히 프레임버퍼는 각 프래그먼트를 처리할 때마다 깊이 값을 읽고, 비교하고, 새 색상을 쓰므로 접근 빈도가 높습니다.
IMR은 프래그먼트마다 VRAM의 프레임버퍼를 읽고 써야 하므로, 넓은 메모리 대역폭이 필요합니다. 데스크톱 GPU는 전용 VRAM과 128~512bit 폭의 메모리 버스로 수백~수천 GB/s의 대역폭을 확보할 수 있고, 전원 콘센트에서 수백 W를 공급받으므로 전력 제약도 적습니다.
반면 모바일 환경은 배터리로 동작하므로 GPU에 할당할 수 있는 전력이 수 W로 제한되고, GPU 전용 메모리 없이 CPU와 시스템 메모리를 공유합니다.
모바일의 대역폭 문제
모바일 기기에서 CPU와 GPU는 하나의 SoC(System on Chip) 안에 통합되어 있으며, LPDDR(Low Power Double Data Rate) 메모리를 함께 사용합니다. 이처럼 하나의 메모리를 공유하는 구조를 통합 메모리 아키텍처(Unified Memory Architecture, UMA) 라 합니다.
UMA 구조에서는 두 가지 제약이 생깁니다.
메모리 버스 폭의 차이. 모바일 SoC의 메모리 버스는 64~128bit으로, 데스크톱(128~512bit)의 절반 이하입니다. 버스 폭이 좁으면 한 클럭당 전송할 수 있는 데이터양이 줄어들어, 모바일의 메모리 대역폭은 25~50 GB/s 수준에 머뭅니다.
클럭(clock): 메모리와 컨트롤러가 한 번 신호를 주고받는 주기입니다. 128bit 버스는 매 클럭마다 16바이트를, 64bit 버스는 8바이트를 전송합니다.
메모리 대역폭과 전력의 관계. LPDDR 메모리에서 데이터를 읽거나 쓸 때마다 메모리 컨트롤러, 메모리 버스, DRAM 셀이 모두 활성화되며 전력을 소비합니다. ARM의 기술 문서에 따르면, 외부 메모리 접근은 칩 내부 메모리 접근에 비해 약 10배 이상의 에너지를 소비합니다. 배터리 전력이 제한적인 모바일 환경에서는 외부 메모리 접근을 줄이는 것이 성능과 전력 효율 모두에 직접적인 영향을 줍니다.
해상도 1920×1080, 60fps 기준으로 프레임버퍼 대역폭을 계산하면 이 제약이 어느 정도인지 확인할 수 있습니다.
위 수치는 모든 픽셀이 정확히 한 번씩만 쓰이고, 깊이 읽기나 오버드로우가 없는 이상적인 경우입니다.
실제로는 프래그먼트마다 깊이를 읽고(4바이트), 테스트를 통과하면 색상과 깊이를 다시 기록(4+4바이트)해야 하므로 픽셀당 12바이트, 약 1.5배가 됩니다. 같은 픽셀을 여러 삼각형이 덮어쓰는 오버드로우가 평균 2x라면 여기에 다시 2배가 곱해집니다.
\[\sim 1\,\text{GB/s} \times 1.5\,(\text{읽기+쓰기}) \times 2\,(\text{오버드로우 2x}) = \sim 3\,\text{GB/s}\]MSAA(멀티샘플 안티앨리어싱)를 적용하면 픽셀당 여러 샘플(4x일 경우 4개)을 저장해야 하므로 프레임버퍼 크기와 대역폭이 샘플 수에 비례하여 증가합니다.
위 예시처럼 1080p, 60fps 기준으로도 프레임버퍼 접근만으로 약 3 GB/s를 소비하는데, 모바일 GPU의 총 대역폭은 25~50 GB/s입니다. 여기에 텍스처 읽기, 버텍스 데이터 로드, 포스트 프로세싱 등이 같은 대역폭을 나눠 써야 하므로, IMR 방식으로는 대역폭이 부족합니다.
모바일 GPU는 이 문제를 해결하기 위해 IMR과 다른 렌더링 방식을 사용합니다.
타일 기반 렌더링의 원리 — TBR과 TBDR
타일 기반 렌더링(Tile-Based Rendering) 은 화면 전체를 한 번에 처리하는 대신, 16×16 또는 32×32 픽셀 크기의 작은 타일로 나누어 하나씩 렌더링하는 방식입니다.
모바일 GPU 칩 내부에는 타일 렌더링을 위한 전용 SRAM인 온칩 타일 메모리(On-Chip Tile Memory) 가 있습니다. GPU 실리콘 위에 직접 배치되어 있어 외부 LPDDR에 비해 접근 속도가 빠르고 전력 소비가 낮습니다.
타일이 충분히 작으면(16×16 또는 32×32 픽셀), 해당 타일의 컬러·깊이·스텐실 버퍼가 이 온칩 타일 메모리에 들어갑니다.
깊이 테스트와 색상 블렌딩이 온칩 타일 메모리 안에서 이루어지면 외부 LPDDR을 거치지 않으므로, IMR에서 문제가 되었던 프래그먼트당 외부 메모리 접근이 대폭 줄어듭니다.
타일 렌더링이 끝나면 최종 컬러만 외부 메모리에 기록하고, 깊이·스텐실 버퍼는 이후 패스에서 필요하지 않으면 기록하지 않고 폐기하여 대역폭을 추가로 절감합니다.
타일 기반 렌더링은 크게 TBR(Tile-Based Rendering)과 TBDR(Tile-Based Deferred Rendering)로 나뉩니다. 둘 다 버텍스 셰이더를 먼저 실행하여 모든 삼각형을 타일별로 분류(비닝)한 뒤, 타일 단위로 프래그먼트 셰이딩을 실행합니다.
차이는 프래그먼트 셰이딩 시점입니다. TBR(ARM Mali, Qualcomm Adreno 등)은 비닝 후 타일 내의 모든 프래그먼트를 셰이딩하며, Early-Z 테스트로 가려진 프래그먼트를 걸러냅니다.
TBDR(Apple GPU/PowerVR 등)은 타일 내에서 가시성 판정(Hidden Surface Removal, HSR)을 먼저 수행하여 최종적으로 보이는 프래그먼트만 셰이딩합니다. 가시성이 확인될 때까지 프래그먼트 셰이딩을 미룬다(deferred)는 뜻에서 TBDR이라는 이름이 붙었습니다.
두 방식 모두 비닝과 타일 렌더링의 두 단계로 구성됩니다.
1단계: Binning (타일 분류)
GPU는 제출된 모든 드로우 콜에 대해 버텍스 셰이더를 실행하여, 각 정점을 화면 좌표(Screen Space)로 변환합니다.
변환이 끝나면 삼각형이 화면의 어떤 타일에 걸치는지 계산하고, 걸치는 타일마다 해당 삼각형을 등록합니다. 하나의 삼각형이 여러 타일에 걸칠 수 있으므로, 같은 삼각형이 여러 타일에 동시에 등록되기도 합니다.
이 결과물이 타일 리스트(Tile List) 입니다. 각 타일에 그려져야 할 삼각형 목록이 기록되며, 이 데이터는 공유 LPDDR에 저장됩니다.
비닝 단계에서는 이전 글에서 다룬 렌더링 파이프라인 중 버텍스 셰이더와 클리핑까지만 실행하고, 여기에 타일 분류를 추가하여 타일 리스트를 구축합니다. 래스터화, 프래그먼트 셰이딩, 테스트/블렌딩은 모두 2단계에서 수행됩니다.
모든 삼각형에 대해 버텍스 셰이더를 실행하고 타일 리스트를 외부 메모리에 기록해야 하므로, 비닝의 비용은 삼각형 수에 비례합니다. 타일 크기도 성능에 영향을 주는데, 타일이 작으면 온칩 타일 메모리 사용량이 줄지만 타일 수가 늘어나 비닝과 타일 전환 오버헤드가 커지고, 타일이 크면 타일당 메모리 요구량이 늘어 동시에 처리할 수 있는 타일 수가 줄어듭니다. GPU 제조사마다 자사 아키텍처에 맞는 크기를 선택하며, Mali는 16×16, Apple GPU는 32×32 픽셀을 사용합니다.
2단계: 타일별 렌더링
두 번째 단계에서 GPU는 타일 리스트에서 해당 타일에 등록된 삼각형 목록을 읽어오고, 온칩 타일 메모리에 컬러·깊이·스텐실 버퍼를 배치합니다.
래스터화, 프래그먼트 셰이딩, 깊이 테스트, 블렌딩 과정에서 읽고 쓰는 컬러·깊이·스텐실 데이터가 모두 이 온칩 타일 메모리에 있으므로, 프래그먼트당 외부 메모리 접근이 대폭 줄어듭니다.
타일의 모든 삼각형 처리가 끝나면 최종 컬러만 외부 메모리의 프레임버퍼에 기록하고, 다음 타일로 이동하여 같은 과정을 반복합니다.
IMR에서는 프래그먼트마다 외부 메모리의 프레임버퍼를 읽고 썼지만, TBR/TBDR에서는 프래그먼트 처리 중 컬러·깊이·스텐실 접근이 온칩 타일 메모리에서 이루어지므로, 외부 메모리 기록은 타일마다 최종 컬러를 한 번 쓰는 것으로 줄어듭니다.
IMR vs TBR/TBDR 비교
이 차이를 파이프라인 전체로 비교하면 다음과 같습니다.
IMR은 프래그먼트를 처리할 때마다 외부 메모리의 깊이 값을 읽고, 새 색상을 쓰므로 외부 메모리 접근량이 프래그먼트 수에 비례합니다. TBR/TBDR은 이 과정이 온칩 타일 메모리에서 이루어지고, 타일의 모든 프래그먼트 처리가 끝난 뒤 최종 색상만 한 번 외부 메모리에 기록합니다.
이러한 이유로 현재 주요 모바일 GPU(Mali, Adreno, Apple GPU)는 타일 기반 아키텍처를 사용합니다.
온칩 타일 메모리의 이점
타일 기반 렌더링의 핵심 자원은 온칩 타일 메모리입니다.
GPU 칩은 하나의 실리콘 다이(silicon die) 위에 연산 유닛, 캐시 등을 집적하는데, 온칩 타일 메모리도 이 다이 위에 SRAM(Static RAM) 으로 만들어집니다. 칩 외부에 별도로 존재하는 LPDDR과는 물리적 위치부터 다르고, 이 차이가 속도와 전력 면에서 이점을 만듭니다.
접근 속도는 외부 LPDDR보다 수십 배 빠릅니다. 칩 내부의 배선이 외부 메모리 인터페이스보다 넓고 빠르므로 대역폭 면에서도 유리합니다. 깊이 테스트나 블렌딩처럼 같은 픽셀 위치를 반복적으로 읽고 쓰는 연산에서 이 차이가 극대화됩니다.
전력 소비도 낮습니다. ARM의 공개 자료에 따르면, 외부 메모리 접근은 칩 내부 메모리 접근에 비해 에너지 소비가 약 10배 이상 높습니다. 배터리로 동작하는 모바일 기기에서 이 차이는 중요합니다.
반면 다이 위의 면적이 제한되므로 용량은 작습니다. 온칩 타일 메모리에는 현재 처리 중인 타일의 색상·깊이·스텐실 버퍼가 들어가는데, 16×16 픽셀 타일 기준으로 색상 버퍼(RGBA8, 4바이트 × 256픽셀)에 1,024바이트, 깊이+스텐실 버퍼(D24S8, 4바이트 × 256픽셀)에 1,024바이트이므로 타일 하나에 약 2 KB가 필요합니다. MSAA를 적용하면 픽셀당 여러 색상·깊이 샘플을 저장해야 하므로 버퍼 크기가 샘플 수만큼 늘어납니다(4xMSAA = 픽셀당 4개 샘플 → 2 KB × 4 = 약 8 KB). 타일 크기를 키우거나 MSAA 수준을 높이면 타일당 메모리 요구량이 늘어나 동시에 처리할 수 있는 타일 수가 줄어듭니다.
GPU 전체의 온칩 타일 메모리 용량은 일반적으로 수백 KB ~ 수 MB 규모입니다.
| 메모리 계층 | 접근 속도 | 전력 소비 | 용량 |
|---|---|---|---|
| 온칩 타일 메모리 (GPU SRAM) | ~1 사이클 | 낮음 | 타일당 수 KB (전체 수백 KB ~ 수 MB) |
| L2 캐시 (GPU 내부) | ~10 사이클 | 중간 | 수백 KB |
| 외부 메모리 (LPDDR) | ~100 사이클 | 높음 | 수 GB |
* 사이클 = GPU 클럭 1회. 1 GHz GPU 기준 1사이클 ≒ 1 ns
* 외부 메모리 접근의 에너지 소비는 온칩 SRAM 대비 약 10배 이상
이러한 속도와 전력의 이점은 렌더링의 여러 단계에서 구체적으로 나타납니다.
깊이 테스트와 블렌딩은 같은 픽셀 위치의 값을 반복적으로 읽고 쓰는 연산입니다. IMR에서는 이 접근이 모두 외부 메모리에서 이루어지지만, TBR/TBDR에서는 온칩 타일 메모리에서 이루어집니다. 깊이 테스트를 통과하지 못한 프래그먼트는 온칩에서 즉시 폐기되고, 반투명 오브젝트의 블렌딩(기존 색상을 읽어 새 색상과 혼합하는 읽기-수정-쓰기 과정)도 외부 메모리 대역폭을 소비하지 않습니다.
MSAA에서도 이점이 큽니다. MSAA는 픽셀당 여러 샘플을 유지하므로 메모리 사용량이 샘플 수에 비례하여 늘어납니다. IMR에서는 이 데이터가 모두 외부 메모리에 상주하여 대역폭 부하가 커지지만, TBR/TBDR에서는 MSAA 샘플이 온칩 타일 메모리에만 존재합니다. 타일이 끝날 때 리졸브(Resolve) — 여러 샘플을 하나의 최종 색상으로 합치는 과정 — 를 수행하여 결과만 외부 메모리에 기록하므로, 4xMSAA를 적용해도 외부 메모리 기록량은 MSAA 없이 렌더링할 때와 동일합니다.
타일 렌더링이 끝나면 최종 색상만 외부 메모리에 기록됩니다. 깊이 버퍼, 스텐실 버퍼, MSAA 샘플 데이터는 타일 렌더링 중에만 필요하므로 외부 메모리에 기록하지 않아도 됩니다.
Unity에서는 이 특성을 활용하는 기능을 제공합니다.
Memoryless 렌더 텍스처는 깊이/스텐실 버퍼처럼 프레임이 끝나면 버려도 되는 데이터에 대해 외부 메모리 자체를 할당하지 않는 설정입니다. 데이터가 온칩 타일 메모리에만 존재하고 외부에 기록되지 않으므로 메모리와 대역폭을 모두 절약합니다.
FrameBufferFetch는 셰이더에서 현재 픽셀의 기존 색상이 필요할 때(예: 커스텀 블렌딩), 외부 메모리를 거치지 않고 온칩 타일 메모리에서 직접 읽는 기능입니다.
Mali / Adreno / Apple GPU 비교
모바일 GPU의 주요 세 계열인 ARM(Mali), Qualcomm(Adreno), Apple은 모두 타일 기반 아키텍처를 사용합니다. 비닝과 온칩 타일 메모리의 기본 원리는 동일하지만, 타일 내에서 불필요한 작업을 줄이는 전략이 각각 다릅니다.
Mali (ARM)
Mali는 ARM이 설계하여 라이센스하는 GPU IP(Intellectual Property) 로, Samsung Exynos, MediaTek Dimensity 등 다양한 SoC에 탑재됩니다. 타일 크기는 16×16 픽셀이 기본이며, 세대별로 아키텍처가 크게 달라(Midgard, Bifrost, Valhall 등) Android 기기 간 GPU 성능 편차가 큽니다.
Mali는 타일 내 불필요한 셰이딩을 줄이기 위해 Forward Pixel Kill(FPK) 를 사용합니다. 프래그먼트의 깊이 값은 래스터화 단계에서 정점 위치를 보간하여 결정되므로, 프래그먼트 셰이더가 실행되기 전에 이미 확정되어 있습니다. FPK는 이 점을 활용하여, 프래그먼트 셰이딩이 진행되는 도중에 같은 픽셀 위치에 깊이 값이 더 작은 불투명 프래그먼트가 도착하면 이미 진행 중이던 먼 쪽 프래그먼트의 셰이딩을 즉시 중단합니다. 이전 글에서 다룬 Early-Z 테스트가 셰이딩 시작 전에 깊이를 비교하여 거부하는 것과 달리, FPK는 셰이딩이 이미 시작된 프래그먼트도 취소할 수 있습니다.
다만 FPK는 셰이딩이 진행 중인 프래그먼트만 취소할 수 있습니다. 먼 쪽 프래그먼트의 셰이딩이 더 가까운 프래그먼트가 도착하기 전에 이미 완료되었다면 그 낭비는 막지 못합니다. 이런 경우를 줄이려면 Early-Z가 셰이딩 전에 최대한 많이 걸러내야 하며, Unity의 Opaque 패스가 기본적으로 불투명 오브젝트를 앞에서 뒤(front-to-back)로 정렬하는 것도 이를 돕기 위해서입니다. 가까운 오브젝트의 깊이가 먼저 기록되면 Early-Z가 뒤쪽 프래그먼트를 거부할 확률이 높아집니다.
깊이 테스트, Early-Z, FPK의 차이
세 기술은 모두 깊이 값을 비교하지만, 동작 시점과 역할이 달라 각각 필요합니다.
깊이 테스트(Z-test) — 프래그먼트 셰이더 이후에 수행됩니다. 셰이딩이 완료된 프래그먼트의 깊이를 깊이 버퍼에 기록된 값과 비교하여, 더 먼 프래그먼트의 결과를 폐기하고 더 가까운 프래그먼트의 깊이를 기록합니다. 최종 이미지의 정확성을 보장하는 필수 단계이지만, 셰이딩을 마친 뒤에야 깊이를 비교하므로, 최종적으로 폐기되는 프래그먼트의 셰이딩 비용까지 그대로 소비됩니다.
Early-Z — 프래그먼트 셰이더 이전에 수행됩니다. 새로 도착한 프래그먼트의 깊이를 깊이 버퍼에 이미 기록된 값과 비교하여, 더 먼 프래그먼트를 셰이딩 없이 폐기합니다. 깊이 테스트와 비교 대상은 같지만, 셰이딩 전에 수행하므로 불필요한 셰이딩 비용을 줄입니다.
FPK — 프래그먼트 셰이딩 도중에 수행됩니다. 새로 도착한 프래그먼트의 깊이를 현재 셰이딩이 진행 중인 프래그먼트의 깊이와 비교합니다. 아직 셰이딩이 끝나지 않아 깊이 버퍼에 기록되지 않은 프래그먼트, 즉 Early-Z가 비교할 수 없는 프래그먼트를 대상으로 합니다.
예를 들어, 프래그먼트 A(z=50)가 Early-Z를 통과하고 셰이딩을 시작합니다. A의 셰이딩이 끝나기 전에 같은 픽셀에 프래그먼트 B(z=10)가 도착하면, 깊이 버퍼에는 A의 값이 아직 기록되지 않은 상태라 B도 Early-Z를 통과합니다. 이때 FPK가 셰이딩 중인 A의 깊이와 B의 깊이를 비교하여, 더 먼 A의 셰이딩을 취소합니다.
반대로, A의 셰이딩이 이미 완료되어 깊이 버퍼에 z=50이 기록된 뒤에 프래그먼트 C(z=80)가 도착하면, A는 파이프라인에 없으므로 FPK가 비교할 대상이 없습니다. 이 경우 Early-Z가 깊이 버퍼의 50과 C의 80을 비교하여 C를 폐기합니다.
정리하면, 깊이 테스트는 셰이딩 이후에 정확성을 보장하고, Early-Z는 셰이딩 이전에 깊이 버퍼의 확정된 깊이로 불필요한 셰이딩을 방지하며, FPK는 셰이딩 도중에 아직 확정되지 않은 진행 중인 깊이까지 비교하여 낭비를 줄입니다.
Adreno (Qualcomm)
Adreno GPU는 Qualcomm Snapdragon SoC에 탑재되며, Android 기기에서 높은 점유율을 가진 모바일 GPU입니다. Adreno는 FlexRender 라 불리는 하이브리드 렌더링 방식을 지원하여, 삼각형이 적어서 Binning 오버헤드가 타일링 이점보다 크면 IMR 경로를, 삼각형이 많고 오버드로우가 발생하는 복잡한 장면에서는 타일 기반 경로를 사용합니다. 이 전환은 드라이버가 장면 특성을 분석하여 자동으로 판단합니다.
타일 기반 경로에서 Adreno는 LRZ(Low Resolution Z-test) 를 사용하여 불필요한 셰이딩을 줄입니다. LRZ는 Binning 단계에서 각 타일의 깊이 정보를 일반 깊이 버퍼보다 훨씬 낮은 해상도로 별도의 버퍼(LRZ 버퍼)에 기록한 뒤, 타일별 렌더링 단계에서 프래그먼트를 처리하기 전에 이 LRZ 버퍼와 비교합니다. 저해상도 깊이보다 확실히 먼 프래그먼트는 정밀한 깊이 테스트나 셰이딩 없이 바로 제거됩니다.
LRZ는 저해상도로 비교하므로 100% 정확하지는 않습니다. 확실히 가려지는 프래그먼트만 제거하고, 경계에 있는 프래그먼트는 보수적으로 통과시킵니다.
그럼에도 대부분의 장면에서 프래그먼트 셰이더에 도달하는 불필요한 프래그먼트를 크게 줄여줍니다. Mali와 마찬가지로, 불투명 오브젝트를 앞에서 뒤로 정렬하면 타일별 렌더링 단계에서 Early-Z가 뒤쪽 프래그먼트를 더 많이 거부할 수 있어 셰이딩 효율이 높아집니다.
Apple GPU
Apple GPU는 Apple이 자체 설계한 GPU로, A-시리즈(iPhone) 및 M-시리즈(iPad, Mac) 칩에 탑재됩니다. 초기에는 Imagination Technologies의 PowerVR 타일 기반 기술을 라이센스하여 사용했으나, A11 Bionic(2017년) 이후부터 자체 설계 GPU 아키텍처로 전환했습니다.
Apple GPU의 HSR(Hidden Surface Removal) 은 타일 내의 모든 삼각형에 대해 래스터화와 깊이 테스트까지만 먼저 수행합니다. 각 삼각형을 래스터화하면서 프래그먼트의 깊이 값을 계산하고 깊이 버퍼와 비교하여, 픽셀마다 가장 가까운 프래그먼트를 갱신합니다. 모든 삼각형이 이 과정을 마치면 각 픽셀 위치에서 보이는 프래그먼트가 결정되고, 그 프래그먼트에 대해서만 셰이더를 실행합니다. TBDR의 “Deferred”는 이처럼 셰이딩을 래스터화와 깊이 테스트 이후로 미루는 것을 뜻합니다.
HSR은 모든 삼각형의 깊이를 먼저 비교한 뒤 보이는 것만 셰이딩하므로, 불투명 오브젝트의 정렬 순서가 성능에 미치는 영향이 크지 않습니다.
세 아키텍처 비교 요약
| 항목 | Mali | Adreno | Apple |
|---|---|---|---|
| 렌더링 방식 | TBR | TBR + IMR 혼합 (FlexRender) | TBDR |
| 타일 크기 | 16×16 | 가변 | 32×32 |
| 오버드로우 최적화 | FPK (셰이딩 중 취소) | LRZ (래스터화 전 제거) | HSR (보이는 것만 셰이딩) |
| 대표 SoC | Exynos, Dimensity | Snapdragon | A-시리즈, M-시리즈 |
세 아키텍처 모두 타일 기반이며, 차이는 타일 내에서 불필요한 작업을 어떻게 줄이느냐에 있습니다. Mali는 이미 진행 중인 셰이딩을 취소(FPK)하고, Adreno는 저해상도 깊이로 조기에 걸러내며(LRZ), Apple은 보이는 것만 셰이딩을 시작(HSR)합니다.
다만 세 기술 모두 불투명 오브젝트에서만 동작합니다. 방식은 다르지만 모두 깊이 값을 비교하여 가려진 프래그먼트의 셰이딩을 생략하는 기술인데, 반투명 오브젝트는 겹치는 모든 레이어를 블렌딩해야 하므로 셰이딩을 생략할 수 없습니다.
오버드로우가 타일 기반 GPU에서 특히 비싼 이유
오버드로우(Overdraw) 는 화면의 같은 픽셀 위치에 여러 오브젝트가 겹치면서 셰이딩이 중복 실행되는 현상입니다. 한 픽셀에 배경, 건물, 캐릭터가 겹치면 해당 픽셀은 세 번 셰이딩되지만, 최종적으로 보이는 것은 가장 앞의 캐릭터뿐이므로 나머지 두 번은 낭비입니다. 앞에서 살펴본 FPK, LRZ, HSR은 모두 이 낭비를 줄이기 위한 기술입니다.
모바일 GPU는 데스크톱에 비해 연산 자원이 훨씬 제한적입니다. ALU(Arithmetic Logic Unit, 연산 유닛) 수는 데스크톱의 수천~수만 개에 비해 약 1,000~2,000개 수준이고, 필레이트(Fill Rate) — 초당 처리 가능한 프래그먼트 수 — 도 데스크톱의 수백억~수천억 픽셀/초에 비해 약 150억~500억 픽셀/초입니다. 타일 기반 렌더링이 절약하는 것은 외부 메모리 대역폭이며, 오버드로우로 인한 셰이더 중복 실행은 이 제한된 연산 예산을 그대로 소비합니다.
불투명 오브젝트는 FPK, LRZ, HSR이 오버드로우를 줄여 주지만, 반투명 오브젝트는 겹치는 모든 레이어를 블렌딩해야 하므로 이 최적화가 적용되지 않습니다. 겹치는 만큼 셰이딩이 그대로 실행됩니다.
모바일 게임에서 반투명 오버드로우가 빈번한 대표적인 요소로는 파티클 시스템, UI, 반투명 머티리얼이 있습니다. 파티클 시스템은 연기, 불꽃, 폭발 등을 표현할 때 반투명 빌보드(Billboard, 항상 카메라를 향하는 사각형) 를 수십~수백 장 겹치며, 각 파티클이 화면의 넓은 영역을 덮을수록 오버드로우가 급격히 늘어납니다. UI도 배경 패널, 그림자, 테두리, 아이콘, 텍스트 등 여러 반투명 레이어가 겹쳐 화면의 넓은 영역을 차지하고, 유리·물·홀로그램 같은 반투명 머티리얼이 서로 겹치는 경우도 마찬가지입니다.
Unity 에디터의 Scene View에서 Overdraw 시각화 모드(상단 드롭다운)를 활성화하면 오버드로우가 발생하는 영역을 색상 강도로 확인할 수 있습니다.
오버드로우와 셰이더 복잡도
오버드로우 배수는 곧 프래그먼트 셰이더 실행 배수이므로, 셰이더가 복잡할수록 오버드로우의 비용이 커집니다. Unlit 셰이더처럼 텍스처 하나만 읽는 경우에는 계산이 가벼워서 오버드로우 2~3x도 견딜 수 있지만, 노멀 맵, 스페큘러, 조명 계산이 포함된 셰이더는 텍스처를 여러 장 읽고 수학 연산을 수십 번 수행합니다. 오버드로우 3x면 이 비싼 셰이더가 3번 반복 실행되므로, 프레임 레이트가 급격히 떨어집니다.
타일 기반 렌더링에서 주의해야 할 추가 사항
앞에서 타일 기반 렌더링이 대역폭을 절약하는 원리와, FPK/LRZ/HSR이 오버드로우를 줄이는 방식을 살펴봤습니다. 하지만 타일 기반 렌더링에는 데스크톱 IMR에서는 신경 쓰지 않아도 되는 추가 고려 사항이 있습니다.
타일 메모리와 Load/Store
렌더링 전에 외부 메모리의 이전 내용을 온칩 타일 메모리로 불러오는 과정을 Load, 렌더링이 끝난 뒤 결과를 외부 메모리에 기록하는 과정을 Store 또는 Resolve 라 합니다.
이 Load/Store가 타일마다 발생하므로, 불필요한 Load나 Store가 늘어나면 타일 기반 렌더링의 대역폭 이점이 상쇄됩니다.
Load는 이전 프레임의 내용이 필요할 때만 발생합니다. Unity에서 카메라의 Clear Flags를 “Solid Color”나 “Skybox”로 설정하면 화면 전체를 새로 그리므로, GPU는 이전 내용을 Load하지 않고 타일 메모리를 직접 초기화합니다.
반면 “Don’t Clear”로 설정하면 이전 프레임의 내용을 유지해야 하므로, GPU는 렌더링 전에 외부 메모리에서 이전 내용을 Load해야 하고 그만큼 대역폭을 소비합니다.
렌더 타깃 전환 비용
GPU가 렌더링 결과를 기록하는 대상을 렌더 타깃(Render Target) 이라 합니다. 기본 렌더 타깃은 화면에 표시되는 프레임 버퍼이지만, 포스트 프로세싱처럼 중간 결과가 필요하면 별도의 렌더 텍스처(Render Texture) 에 렌더링하기도 합니다.
GPU는 같은 대상을 동시에 읽고 쓸 수 없으므로, 렌더 텍스처에 그린 장면을 읽어서 후처리한 결과는 다른 렌더 텍스처나 프레임 버퍼에 기록해야 합니다. 이처럼 한 프레임을 렌더링하는 도중에 출력 대상을 바꾸는 것이 렌더 타깃 전환이며, 중간 결과가 필요한 한 피할 수 없습니다.
데스크톱 IMR은 렌더링 데이터가 항상 외부 메모리(VRAM)에 있어 렌더 타깃을 전환해도 쓰기 대상만 바꾸면 됩니다. 반면 타일 기반 렌더링에서는 데이터가 온칩 타일 메모리에 있으므로, 전환할 때마다 현재 내용을 Store하고 새 렌더 타깃을 Load해야 하며, 전환이 잦을수록 대역폭 소비가 늘어납니다.
예를 들어 블룸은 밝은 부분 추출 → 블러(수평·수직 별도 패스) → 원본 합성 과정에서 단계마다 쓰기 대상이 바뀌어 최소 4번의 전환이 발생하고, 피사계 심도(Depth of Field)나 모션 블러(Motion Blur)처럼 별도 패스가 필요한 효과를 추가하면 그만큼 전환 횟수도 늘어납니다. 모바일에서 포스트 프로세싱 패스가 많을수록 Load/Store 대역폭 비용이 커지는 이유입니다.
Alpha Test와 타일 기반 GPU
텍스처의 알파 값을 기준값과 비교하여 기준 이하인 프래그먼트를 폐기하는 기법을 알파 테스트(Alpha Test) 라 부릅니다.
현대 셰이더에서는 discard(GLSL) 또는 clip(HLSL) 명령어로 구현합니다.
나뭇잎이나 철조망처럼 윤곽이 복잡한 형태는 폴리곤으로 정밀하게 모델링하면 삼각형 수가 많아지므로, 단순한 사각형 폴리곤에 알파 채널이 포함된 텍스처를 입힌 뒤 알파 값이 낮은 부분을 폐기하여 형태를 표현합니다.
타일 기반 GPU에서 알파 테스트는 특별한 문제를 일으킵니다. 앞에서 살펴본 것처럼 깊이 값은 래스터화 단계에서 확정되며, LRZ, HSR, FPK는 이를 활용하여 셰이딩 전이나 도중에 불필요한 프래그먼트를 걸러냅니다.
그런데 discard가 실행되면 해당 프래그먼트의 색상뿐 아니라 깊이도 기록되지 않습니다. 깊이 자체는 래스터화 시점에 알고 있지만, 셰이더가 프래그먼트를 폐기할 수 있으므로 그 깊이가 최종적으로 유효한지는 셰이더 실행이 끝나야 결정됩니다.
Early-Z와 LRZ, HSR은 이 프래그먼트의 깊이를 깊이 버퍼에 미리 반영할 수 없고, FPK는 셰이딩 중인 discard 프래그먼트의 깊이를 기준으로 다른 프래그먼트를 취소할 수 없습니다. discard된 프래그먼트 뒤의 프래그먼트를 취소하면, 해당 픽셀에 유효한 프래그먼트가 없어지기 때문입니다.
따라서 discard가 포함된 셰이더에서는 해당 드로우 콜에 대해 깊이 기반 최적화가 비활성화되거나 효과가 크게 줄어듭니다.
discard는 렌더링 결과의 정확성을 위해 반드시 실행되어야 하는 셰이더 로직입니다. 나뭇잎 텍스처의 투명한 부분을 폐기하지 않으면 사각형 폴리곤이 그대로 보이기 때문입니다. 반면 깊이 기반 최적화는 성능을 높이기 위한 것이므로, 비활성화해도 렌더링 결과는 동일합니다. GPU는 정확한 이미지를 먼저 보장해야 하므로, discard가 포함된 셰이더를 반드시 실행하는 대신 해당 드로우 콜에 대해 깊이 기반 최적화를 비활성화하거나 효과를 크게 줄입니다.
따라서 모바일에서는 가능하면 discard 대신 알파 블렌딩(Alpha Blending) 을 사용하는 편이 유리합니다. 알파 블렌딩은 프래그먼트를 폐기하지 않고 알파 값에 따라 기존 색상과 혼합하는 방식으로, 반투명 오브젝트로 처리되어 오버드로우 비용은 발생하지만 discard를 사용하지 않으므로 다른 불투명 오브젝트의 깊이 기반 최적화에 영향을 주지 않습니다.
깊이 기반 최적화는 드로우 콜 단위로 적용되므로, discard를 사용하지 않는 불투명 오브젝트들은 FPK, LRZ, HSR의 이점을 그대로 유지합니다. 알파 테스트가 반드시 필요한 경우에는 해당 오브젝트의 수를 최소화하는 것이 좋습니다.
삼각형 수와 Binning 부하
데스크톱 IMR에서는 각 삼각형이 버텍스 셰이딩을 마치면 곧바로 프래그먼트 셰이딩으로 넘어갑니다. 여러 삼각형이 파이프라인의 서로 다른 단계에 동시에 있으므로, 한 삼각형의 프래그먼트 처리와 다른 삼각형의 버텍스 처리가 동시에 진행될 수 있습니다.
반면 타일 기반 렌더링에서는 모든 삼각형에 대해 버텍스 셰이더를 실행하고 각 삼각형이 어느 타일에 속하는지 분류하는 Binning 단계를 먼저 거쳐야 타일별 렌더링이 시작됩니다. 삼각형 수가 많으면 Binning 단계가 길어지고, 그동안 프래그먼트 처리는 시작할 수 없습니다.
Binning과 프래그먼트 처리 중 어느 쪽이 병목인지는 Arm Mobile Studio(Mali), Snapdragon Profiler(Adreno), Xcode GPU Profiler(Apple) 등 벤더별 GPU 프로파일링 도구에서 두 단계의 시간을 분리하여 확인할 수 있습니다.
모바일에서 Binning 병목을 줄이려면 LOD(Level of Detail)로 먼 오브젝트의 삼각형 수를 줄이거나, 카메라에 보이지 않는 오브젝트를 컬링하여 GPU에 제출되는 총 삼각형 수를 관리해야 합니다.
마무리
이 글에서는 모바일 GPU가 제한된 대역폭 안에서 렌더링 효율을 높이는 방법과, 타일 기반 아키텍처에서 추가로 고려해야 할 사항을 살펴보았습니다.
- 모바일 GPU는 CPU와 시스템 메모리(LPDDR)를 공유하며, 메모리 대역폭이 25~50 GB/s로 데스크톱의 약 1/10 수준입니다.
- 타일 기반 렌더링(TBR/TBDR)은 화면을 타일로 분할하여 온칩 타일 메모리에서 래스터화, 깊이 테스트, 블렌딩, MSAA를 처리하고, 최종 색상만 외부 메모리에 기록합니다.
- Mali(FPK), Adreno(LRZ), Apple(HSR)은 각각 다른 방식으로 가려진 프래그먼트의 셰이딩을 줄이지만, 깊이 정보를 기반으로 동작하므로 불투명 오브젝트에서 효과적입니다.
- 반투명 오브젝트는 겹치는 모든 레이어를 블렌딩해야 하므로 이 최적화의 도움을 받지 못하고, 오버드로우가 프래그먼트 처리 비용을 직접 증가시킵니다.
- 렌더 타깃 전환의 Load/Store 비용,
discard에 의한 깊이 기반 최적화 비활성화, Binning 단계의 삼각형 수 비례 비용은 타일 기반 렌더링 고유의 고려 사항입니다.
모바일 GPU 아키텍처의 핵심은 제한된 대역폭과 연산 자원 안에서 효율을 극대화하는 것입니다. 타일 기반 렌더링과 온칩 타일 메모리는 외부 메모리 접근을 줄이고, FPK·LRZ·HSR은 가려진 프래그먼트의 불필요한 셰이딩을 제거합니다.
관련 글
시리즈
- GPU 아키텍처 (1) - GPU 병렬 처리와 렌더링 파이프라인
- GPU 아키텍처 (2) - 모바일 GPU와 TBDR (현재 글)
전체 시리즈
- 게임 루프의 원리 (1) - 프레임의 구조
- 게임 루프의 원리 (2) - CPU-bound와 GPU-bound
- 렌더링 기초 (1) - 메쉬의 구조
- 렌더링 기초 (2) - 텍스처와 압축
- 렌더링 기초 (3) - 머티리얼과 셰이더 기초
- GPU 아키텍처 (1) - GPU 병렬 처리와 렌더링 파이프라인
- GPU 아키텍처 (2) - 모바일 GPU와 TBDR (현재 글)
- Unity 렌더 파이프라인 (1) - Built-in과 URP의 구조
- Unity 렌더 파이프라인 (2) - 드로우콜과 배칭
- Unity 렌더 파이프라인 (3) - 컬링과 오클루전
- 스크립트 최적화 (1) - C# 실행과 메모리 할당
- 스크립트 최적화 (2) - Unity API와 실행 비용
- 메모리 관리 (1) - 가비지 컬렉션의 원리
- 메모리 관리 (2) - 네이티브 메모리와 에셋
- 메모리 관리 (3) - Addressables와 에셋 전략
- UI 최적화 (1) - 캔버스와 리빌드 시스템
- UI 최적화 (2) - UI 최적화 전략
- 조명과 그림자 (1) - 실시간 조명과 베이크
- 조명과 그림자 (2) - 그림자와 후처리
- 셰이더 최적화 (1) - 셰이더 성능의 원리
- 셰이더 최적화 (2) - 셰이더 배리언트와 모바일 기법
- 물리 최적화 (1) - 물리 엔진의 실행 구조
- 물리 최적화 (2) - 물리 최적화 전략
- 파티클과 애니메이션 (1) - 파티클 시스템 최적화
- 파티클과 애니메이션 (2) - 애니메이션 최적화
- 프로파일링 (1) - Unity Profiler와 Frame Debugger
- 프로파일링 (2) - 모바일 프로파일링
- 모바일 전략 (1) - 발열과 배터리
- 모바일 전략 (2) - 빌드와 품질 전략