CS/그래픽스

[Rendering Optimization] Stage 1 : Input Assembler (Data Fetch & Assembly)

tae-woong 2026. 1. 20. 18:42

하드웨어가 알아서 수행하는 영역입니다.

 

이곳의 내부 로직은 개발자가 수정할 수 없습니다.

 

대신, 하드웨어가 데이터를 효율적으로 읽을 수 있도록 "데이터 형식(Format)을 맞춰주는 것"만 신경 쓰면, 나머지는 시스템이 알아서 최적화를 진행합니다.

 

개요

이 단계는 GPU가 메모리(VRAM)로부터 정점 데이터(Vertex)와 인덱스 데이터(Index)를 읽어 들이는(Fetch) 단계입니다.

 

CPU가 보낸 작업 지시서(Draw Call)를 바탕으로, 흩어져 있는 데이터들을 모아 점, 선, 삼각형 같은 기본 도형(Primitive)으로 조립합니다.

 

여기서의 최적화 핵심은 "데이터 다이어트"입니다.

 

아무리 GPU 성능이 좋아도, 데이터를 가져오는 통로(Bus)가 막히면 병목이 생기기 때문입니다.

 

<핵심 목표>

  1. Bandwidth Optimization : 메모리에서 GPU로 전송되는 데이터의 크기를 줄여 대역폭을 확보합니다.
  2. Vertex Cache Efficiency : 중복된 정점을 다시 읽지 않도록 인덱싱을 활용하여 캐시 적중률(Cache Hit)을 높입니다.

 

최적화 방법

1. Vertex Format Optimization (버텍스 포맷 최적화)

  • 설명 : Input Assembler가 메모리에서 데이터를 퍼올 때, 한 번에 더 가볍게 가져올 수 있도록 정점 데이터 구조(Struct)를 최적화하는 기법입니다.
    • Unused Data Removal : 사용하지 않는 채널(Vertex Color, Tangent, UV3 등)은 과감히 데이터 구조에서 뺍니다.
    • Precision Reduction : 데이터 타입을 Float32 (4Byte)에서 Float16 (Half, 2Byte) 혹은 Byte (1Byte) 등으로 압축(Packing)하여 저장합니다.
  • 지금 + 이후 단계에서 효과 :
    • Stage 1 (IA) 자체 : 데이터 전송 대역폭(Bandwidth) 사용량이 획기적으로 줄어들어, 발열과 배터리 소모가 감소합니다. (모바일 최적화의 핵심)
    • Stage 2 (VS) : 버텍스 셰이더가 한 번에 캐싱할 수 있는 정점 개수가 늘어나 연산 효율이 좋아집니다.
  • 장점 :
    • 메모리 용량 확보 : 앱의 런타임 메모리 사용량과 빌드 용량이 동시에 줄어듭니다.
    • 모바일 성능 향상 : 메모리 대역폭이 좁은 모바일 기기에서 프레임 레이트 방어에 매우 효과적입니다.
  • 단점 :
    • 정밀도 이슈 (Artifacts) : 좌표를 과하게 압축할 경우 모델의 위치가 미세하게 어긋나거나(Jitter), 텍스처 매핑이 밀리는 현상이 발생할 수 있습니다. (Positon은 float, 나머지는 half 권장)
    • 추가 연산 필요 : 데이터를 압축해서 보냈다면, 버텍스 셰이더에서 다시 풀어서(Unpacking) 써야 하는 경우도 있어 미세한 연산 비용이 추가될 수 있습니다.
  • ※ 헷갈리기 쉬운 포인트 : Vertex Format Optimization(1단계) vs Vertex Shader Precision(2단계)
    • 1단계 (Format) : "메모리에 저장된 택배 상자 크기"를 줄이는 것. (목적: 전송 속도 향상 / 대역폭 절약)
    • 2단계 (Precision) : "셰이더 내부 계산기의 자릿수"를 줄이는 것. (목적: 연산 속도 향상 / ALU 절약)
    • 보통 1단계에서 줄여서 보내면 2단계에서도 자연스럽게 줄어든 자료형을 쓰게 됩니다.

2. Indexed Rendering (인덱스 버퍼 사용)

  • 설명 : 삼각형을 그릴 때 정점 3개를 매번 새로 보내는 것이 아니라, 중복되는 정점은 하나만 보내고 '번호표(Index)'만 나열해서 재사용하는 기법입니다.
    • 예) 사각형을 그릴 때 삼각형 2개가 필요함 (정점 6개). 하지만 공유되는 점을 활용하면 정점 4개 + 인덱스 6개로 처리 가능.
  • 지금 + 이후 단계에서 효과 :
    • Stage 1 (IA) : 중복된 정점 데이터를 메모리에서 읽지 않아도 되므로 대역폭이 절약됩니다.
    • Stage 2 (VS) : Post-Transform Cache라는 GPU 기능을 통해, "어? 2번 정점 아까 계산했지?" 하고 셰이더 연산을 건너뛰고 결과를 재사용합니다. (쉐이더 호출 횟수 감소)
  • 장점 :
    • 필수적인 최적화 : 현대의 거의 모든 3D 메쉬는 기본적으로 인덱스 버퍼를 사용하여, 버텍스 셰이더 부하를 평균 1.5배~3배까지 줄여줍니다.
    • 메모리 절약 : 정점 데이터(약 32~64Byte)보다 인덱스 데이터(2~4Byte)가 훨씬 작기 때문에 전체 용량이 줄어듭니다.
  • 단점 :
    • 구현 복잡도 : 절차적 생성(Procedural Mesh) 등을 코드로 직접 짤 때 인덱스 순서(Winding Order)를 맞추기가 까다롭습니다.
    • Hard Edge 표현 불가 : 큐브의 각진 모서리처럼 완전히 꺾인 면은 정점을 공유할 수 없어(노말 값이 다르므로), 정점을 분리(Split)해야 하므로 인덱싱 효율이 떨어집니다.
  • ※ 헷갈리기 쉬운 포인트 : Vertex Buffer vs Index Buffer
    • Vertex Buffer : "내용물" (위치, 색상, UV 등 무거운 데이터)
    • Index Buffer : "순서표" (0, 1, 2, 2, 3, 0... 가벼운 정수 데이터)

3. Attribute Interleaving (인터리브드 배열)

  • 설명 : 데이터를 메모리에 저장할 때 위치 배열 따로, 노말 배열 따로(SoA) 저장하는 것이 아니라, 하나의 정점에 대한 모든 정보(위치+노말+UV)를 한 덩어리로 묶어서(AoS) 나열하는 방식입니다.
    • GPU는 메모리를 읽을 때 덩어리(Cache Line)로 읽어오기 때문에, 한 정점의 데이터를 한곳에 모아두는 것이 유리합니다.
  • 지금 단계에서 효과 :
    • Stage 1 (IA) : 캐시 적중률(Cache Hit Rate)이 높아져서 메모리 읽기 대기 시간(Latency)이 줄어듭니다.
  • 장점 :
    • 데이터를 순차적으로 읽는 일반적인 렌더링 상황에서 전송 효율이 가장 좋습니다.
  • 단점 :
    • 특정 속성(예: 위치)만 따로 수정하고 싶을 때도 전체 구조를 건드려야 해서 데이터 갱신이 불편할 수 있습니다.