Scientia Conditorium
[정리] 리얼 타임 렌더링(Real-Time Rendering, 4/e) 3장 - 그래픽 처리 장치 본문
[정리] 리얼 타임 렌더링(Real-Time Rendering, 4/e) 3장 - 그래픽 처리 장치

그래픽 처리 장치(Graphics Processing Unit)
- CPU에 비해 전용 그래픽 하드웨어가 갖는 장점은 계산 속도가 빠르다는 것뿐이지만 속도 향상은 매우 중요하다.
- 하드웨어 정점 처리를 포함하는 최초의 소비자용 그래픽 칩 : NVIDIA GeForce 256 (1999)
- 이전에 사용 가능한 래스터 및 전용 칩과 GeForce 256을 구별하고자 그래픽 처리 장치(GPU) 용어 만듬
- GPU는 고도로 병렬화활 수 있기 때문에 속도가 매우 빠르다.
- GPU에서 프로그래밍 가능한 쉐이더가 어떻게 병렬성을 갖는가를 아는 것이 중요
- 모든 처리 장치가 당면하는 문제는 지연(Latency)
- 데이터에 접근하는 데는 일정한 시간이 필요
- 지연에 대한 기본 개념은 처리할 정보가 처리 장치에서 멀어질수록 대기 시간이 길어지는 것
- 메모리칩에 저장한 정보는 지역 레지스터에 저장한 것보다 접근 시간이 더 오래 걸림
- 데이터 검색을 기다림으로 인해 처리 장치가 정지 대기(Stall)돼 성능이 떨어지는 것이 요점
데이터 - 병렬 아키텍처
- GPU 칩 영역의 대부분은 수천 개의 쉐이더 코어라 하는 대규모 처리 장치 집합으로 구성
- GPU는 정렬된 유사한 데이터 집합을 차례대로 처리하는 스트림 프로세서(stream processor)
- 이러한 유사성(ex. 정점이나 픽셀 집합)으로 인해 대규모 병렬 방식으로 처리 가능
- 병렬 처리 연산이 최대한 독립적으로 일어남
- 병렬 처리 중 병렬 처리 중인 다른 부분에 정보가 필요 없게 하고 쓰기 가능한 메모리 위치를 공유하지 않음
- 프로세서들이 일찍 (계산이)끝나더라도 제일 늦은 프로세서가 끝날 때까지 대기하게 돼 성능 저하 원인
- 데이터를 처리할 수 있는 최대 속도로 정의되는 처리량(Throughput)에 최적화
- 캐시 메모리와 제어 로직 전용 칩 영역이 적기 때문에 각 쉐이더 코어의 지연 시간은 CPU보다 높음
- GPU는 연산 수행 논리를 데이터에서 분리
- 2천 개의 프래그먼트를 현대 GPU로 전환하면 프래그먼트에 대한 각 픽셀 쉐이더 호출(invocation)은 스레드(thread)라 불림
- 이 스레드는 CPU 스레드와 다름
- 쉐이더의 입력값에 대한 약간의 메모리와 쉐이더 실행에 필요한 레지스터 공간으로 이뤄짐
- 동일 쉐이더 프로그램을 사용하는 스레드는 집합으로 묶임 : NVIDIA의 워프(warp), AMD의 웨이브프론트(wavefront)
- 8 ~ 64개 사이 일정 수의 GPU 쉐이더 코어에서 실행돼 있으며, SIMD 처리를 사용
- 워프의 실행은 단일 GPU 처리 장치의 예와 유사
- 각 스레드는 SIMD 레인(lane)에 할당
- 실행할 수 있는 2천 개의 스레드가 있다고 가정
- NVIDIA 워프는 32개 스레드를 가짐
- 2000 / 32 = 62.5 워프이기 때문에 63개의 워프가 할당되고 63번째 워프는 절반이 빈 형태
- 쉐이더 프로그램은 32개 처리 장치 모두가 락스텝(lock-step) 형태로 처리
- 메모리 인출을 만나면 모든 스레드가 동시에 만나게 됨
- 인출은 이 스레드 워프가 정지 대기할 것이라고 결과를 기다리는 모든 장치에 전달
- 정지 대기 대신 워프는 다른 32개 스레드의 워프로 교체돼 32코어에서 실행
- 각 스레드 안의 데이터 워프를 변경시키지 않기 때문에 단일 처리 장치 시스템에서처럼 빠름
- 각 스레드는 각자의 레지스터를 가지며 각 워프는 실행되는 연산을 기록
- 새 워프로 교체하는 것은 다른 스레드의 집합에서 코어의 집합으로 단순히 가리키는 것만이 바뀜(다른 부하 없음)
- 워프는 모두 완료될 때까지 실행되거나 교체
- 워프-교체(warp-swapping)는 모든 GPU에서 사용되는 주된 지연 은닉(latency-hiding) 메커니즘
- 쉐이더 프로그램의 구조체는 효율성에 영향을 주는 중요한 특징 중 하나
- 중요한 것은 각 스레드가 사용하는 레지스터의 양
- 필요한 레지스터가 많을수록 더 적은 스레드, 즉 더 적은 워프가 GPU에 거주할 수 있음
- 워프의 부족은 치환으로 완화시킬 수 없는 정지 대기를 의미
- 거주하는 워프를 비행 중(in flight)이라고 하며, 그 수를 점유율(occupancy)이라고 함
- 높은 점유율은 처리를 위한 많은 워프가 가용하다는 것으로, 쉬는 처리 정치가 적을 가능성이 높음
- 전체적인 효율성에 영향을 주는 다른 인자는 동적 분기(Dynamic branching)
- if 명령과 반복문으로 인해 발생
- 일부 혹은 하나의 스레드가 if 명령에 의해 다른 경로를 타면 워프는 반드시 두 분기를 실행해야 함.
이러면 각 특정 스레드에서 불필요한 결과를 버리는 문제가 발생하는 데 이것이 스레드 분산(thread divergence)
- 일부 혹은 하나의 스레드가 if 명령에 의해 다른 경로를 타면 워프는 반드시 두 분기를 실행해야 함.
- if 명령과 반복문으로 인해 발생
GPU 파이프라인 개요
- 렌더링 파이프라인의 GPU 구현 순서
- 버텍스 쉐이더
- 완전히 프로그래밍 가능한 단계
- 지오메트리 구조 처리 단계를 구현하는 데 사용
- 테셀레이션
- 지오메트리 쉐이더
- 완전히 프로그래밍 가능한 단계
- 기본체(점, 선, 삼각형)의 정점 위에서 처리
- 기본체 단위 음영 연산을 처리하고, 기본체를 소멸시키거나 새로운 것을 생성하는 데 사용
- 테셀레이션, 지오메트리 둘 다 선택적이라 모든 GPU가 지원하지 않음
- 클리핑
- 고정 함수 하드웨어에서 구현
- 화면 매핑
- 윈도우와 뷰 볼륨 설정에 영향 받음
- 내부적으로는 단순한 크기 조절과 위치 재조정으로 구성
- 삼각형 설정 & 탐색
- 고정 함수 하드웨어에서 구현
- 픽셀 쉐이더
- 완전히 프로그래밍 가능한 단계
- 병합기
- 프로그래밍 가능하지는 않지만 설정 가능
- 넓은 범위의 연산을 처리하도록 설정할 수 있음
- Z버퍼, 혼합(Blend), 스텐실(Stencil), 다른 출력과 연관된 버퍼의 변경을 담당
- 픽셀 쉐이더와 병합 단계가 함께 실행돼 픽셀 처리 단계를 형성
- 버텍스 쉐이더
프로그래밍 가능한 쉐이더 단계
- 쉐이더 프로그램은 통합된 쉐이더 설계를 사용
- 정점, 픽셀, 지오메트리 구조, 테셀레이션 관련 쉐이더가 공통된 프로그래밍 모델을 공유한다는 것
- 내부적으로 동일한 명령 집합 구조(ISA, Istruction Set Architecture)
- 버텍스 쉐이더와 픽셀 쉐이더 코어가 개별 풀을 가진 GPU는 이상적으로
모든 코어를 바쁘게 유지하기 위한 작업 부포가 미리 지정돼 있음 - 통합 쉐이더 코어로 GPU는 이 부하를 어떻게 조정할지 결정할 수 있음
- 쉐이더는 C언어와 비슷한 형태
- DirectX : HLSL(High-Level Shading Language)
- OpenGL : GLSL(opnGL Shading Language)
- HLSL은 가상머신 바이트코드로 컴파일될 수 있음
- 기본 데이터형은 32비트 단일 정밀도 부동소수점 스칼라와 벡터
- 벡터는 단지 쉐이더 코드의 일부이며 하드웨어에서 지원하지 않음
- 현대 GPU에서 32비트 정수와 64비트 부동소수점 역시 원천적으로 지원
- 부동소수점 벡터는 위치, 법선 벡터는 행렬 행, 컬러, 텍스처 좌표 같은 데이터를 포함
- 정수는 계수기(counters), 색인(indices), 비트마스크(bitmasks) 등을 표현하는 데 사용
- 구조체, 배열, 행렬 같은 혼합 데이터형도 지원
- 그리기 호출(드로우콜, Draw call)은 기본체 집합을 그리는 그래픽 API를 호출해 파이프라인이 실행되고 쉐이더를 실행하게 함
- 각 프로그래밍 가능한 쉐이더 단계는 입력의 2가지 형을 가짐
- 균일 입력(uniform input) : 드로우콜 동안 상수로 유지되는 값
- 범용 입력(varying input) : 삼각형의 정점이나 래스터화에서 오는 데이터
- 텍스처는 특별한 종류의 균일 입력으로 한때 표면에 적용되는 컬러 이미지로만 사용됐으나
이제는 임의의 데이터의 큰 배열로 간주
- 텍스처는 특별한 종류의 균일 입력으로 한때 표면에 적용되는 컬러 이미지로만 사용됐으나
- 기본 가상 머신(underlying virtual machine)
- 다른 형의 입력과 출력에 대한 특별한 래지스터를 제공
- 균일하게 하고자 사용할 수 있는 상수 레지스터(constant registers)의 수는
다양한 입력이나 출력에 사용할 수 있는 레지스터보다 훨씬 큼- 범용 입력과 출력이 각 정점이나 픽셀에 대해 따로 저정해야 하기 때문에 필요한 수량에 제한이 있음
- 균일 입력은 한 번 저장되고 드로우콜의 모든 정점이나 픽셀에서 재사용
- 스크래치 공간(scratch space)에 사용되는 범용 임시 레지스터(temporary register)도 있음
- 모든 유형의 레지스터는 임시 레지스터 안의 정수 값을 사용해 배열 색인을 할 수 있음
- 그래픽 계산에서 공통적인 연산은 현대 GPU에서 효율적으로 실행
- 쉐이딩 언어는 이 연산의 대부분을 공개하며 연산자 * 나 + 등을 사용
- 나머지는 내재 함수로 공개돼 있으며 GPU에 최적화
- 벡터 정규화나 반사, 외적, 행렬 전치와 행렬식 계산 등과 같은 더 복잡한 연산 함수도 있음
- 쉐이더는 2가지 종류의 흐름 제어를 지원
- 정적 흐름 제어(static flow control) : 코드 흐름이 드로우콜 안에서 고정적
- 동일 쉐이더가 다양한 다른 상황에서 사용할 수 있음
- 모든 호출(invocations)은 동일 코드 경로를 갖기에 스레드 분산(thread divergence)이 없음
- 동적 흐름 제어(dynamic flow control) : 범용 입력의 값에 기반을 두며 각 프래그먼트가 코드를 다르게 실행
- 정적 흐름 제어보다 훨씬 강력하지만 쉐이더 호출 사이에 코드 흐름이 비정상적으로 변경되는 경우
성능 저하가 일어날 수 있음
- 정적 흐름 제어보다 훨씬 강력하지만 쉐이더 호출 사이에 코드 흐름이 비정상적으로 변경되는 경우
- 정적 흐름 제어(static flow control) : 코드 흐름이 드로우콜 안에서 고정적
프로그래밍 가능한 음영과 API의 진화
- NVIDIA의 GeForce 3 : 프로그래밍 가능한 버텍스 쉐이더를 지원한 최초의 GPU
- DirectX 8.0과 OpenGL Extension을 통해 공개
- 쉐이더 모델 2.0 (SM, Shader Model)
- DirectX에서 다른 쉐이더 능력을 가진 하드웨어 사이를 구분하고자 도입한 개념
- 진정한 프로그래밍 가능한 버텍스와 픽셀 쉐이더
- 비슷한 기능성이 OpenGL에서 다양한 확장을 통해 공개
- 쉐이더에서 흐름 제어 허용 및 추가
- 쉐이더 모델 3.0
- 동적 흐름 제어 추가
- 버텍스 쉐이더에서 텍스처 읽기 지원 추가
- 추가 기능 요구 사항을 반영해 더욱 더 증가된 자원 지원 추가
- XBOX 360, 플레이스테이션3 게임 콘솔에 쉐이더 모델 3.0 수준의 GPU 장착
- 쉐이더 모델 4.0
- DirectX 10.0에서 포함
- 지오메트리 쉐이더와 스트림 출력 등 주요한 여러 기능이 도입
- 모든 쉐이더(버텍스, 픽셀, 지오메트리)에 대한 균일 프로그래밍 모델을 포함하며 통합 쉐이더 설계 방식으로 구성
- 정수 데이터형의 지원(비트 연산 포함)
- OpenGL 3.3에서 GLSL 3.30의 도입 역시 비슷한 쉐이더 모델을 제공
- 쉐이더 모델 5.0
- DirectX 11과 함께 테셀레이션 단계쉐이더와 컴퓨트 쉐이더 추가
- CPU 멀티프로세싱을 더 효과적으로 사용 가능
- OpenGL 4.0부터 테셀레이션 추가, 4.3부터 컴퓨트 쉐이더 추가
- 2013년 AMD의 Mantle API
- 그래픽 하드웨어의 부하 대부분을 걷어내고 이 제어를 개발자에게 직접 제공
- 리팩토링과 동시에 효과적인 CPU 멀티프로세싱을 지원
- CPU가 드라이버에서 사용하는 시간을 엄청나게 감소
- 좀 더 효과적인 CPU 다중 프로세서 지원에 집중하게 함
- 2015년에 마이크로소프트가 이 API 개념을 채용해 DirectX 12에 적용
- 새 GPU 기능성을 공개하지는 않았고 DirectX 11.3과 동일 하드웨어 기능을 제공
- 최신 GPU 아키텍처에 더 잘 매핑되는 근본적인 API의 재설계
- 애플은 Metal이라 불리는 자체 저부하 API를 2014년에 공개
- iPhone 5S, iPad Air 같은 모바일 장치에서 먼저 사용
- 1년 후 OS X El Capitan을 통해 새로운 매킨토시에서 사용 가능
- 효율성을 넘어서 CPU 사용을 감소시키는 것은 전력을 절약할 수 있는 것으로 모바일 장치에서 중요
- 이 API는 고유의 쉐이딩 언어를 가지며 그래픽과 GPU 계산 프로그램 모두 사용
- 2016년, AMD는 Mantle 작업을 크로노스 그룹에 기부했으며 Vulkan이라는 자체 API를 공개
- OpenGL과 같이 여러 운영체제에서 작동
- 쉐이더와 일반 GPU 계산에서 둘 다 사용 가능한 새로운 고수준 중간 언어인 SPIR-V를 사용
- 미리 컴파일된 쉐이더는 무겁지 않으며 필요한 기능을 지원하는 어떤 GPU에서든 사용 가능
- 디스플레이 윈도우가 필요하지 않는 그래픽이 아닌 GPU 계산에서 사용 가능
- 다른 부하가 적은 드라이버와의 차이는 Vulkan이 워크스테이션부터 모바일 장치까지 지원한다는 점
- 모바일 장치에서는 표준적으로 OpenGL ES를 사용
- ES(Embedded System)의 약어이며 API 자체가 모바일 장치를 고려해서 개발
- OpenGL ES 3.0은 2012년에 공개
- 다중 렌더 타겟, 텍스처 압축, 변환 피드백, 인스턴싱 및 훨씬 더 다양한 텍스처 포맷과 방식을 지원
- OpenGL ES 3.1에서 컴퓨트 쉐이더 추가
- OpenGL ES 3.2에서 다른 기능과 함께 지오메트리 쉐이더와 테셀레이션 쉐이더 추가
- OpenGL ES에서 파생된 브라우저 기반 API인 WebGL은 자바스크립트로 호출
- 2011년에 공개된 뒤에 대부분의 모바일 장치에서 사용 가능했으며 OpenGL Es 2.0에 비해 기능적으로도 동일
- WebGL 2는 OpenGL ES 3.0 지원을 가정
- 크로스 플랫폼이라 모든 PC와 거의 대부분의 모바일 장치에서 동작
- 드라이버 승인이 브라우저에 의해 처리.
심지어 한 브라우저가 특정 GPU나 확장을 지원하지 않아도 다른 브라우저가 지원 - 코드는 컴파일되지 않고 해석(interpret)되며, 단지 텍스처 에디터만이 개발에 필요
- 디버거(Debugger)가 대부분의 브라우저에 내장돼 있으며, 어떤 웹 사이트에서 실행되는 코드든 디버깅 가능
- 프로그램은 웹 사이트나 깃허브에 올려 제공될 수 있음
버텍스 쉐이더
테셀레이션 단계
지오메트리 쉐이더
픽셀 쉐이더
병합 단계
컴퓨트 쉐이더
'프로그래밍 > 컴퓨터 그래픽스' 카테고리의 다른 글
| 레이 트레이싱 공부#001 - Ray Tracing in One Weekend (0) | 2025.11.19 |
|---|---|
| [정리] 리얼 타임 렌더링(Real-Time Rendering, 4/e) 2장 - 그래픽 렌더링 파이프라인 (0) | 2025.11.02 |
| [OpenGL 009] Visual Studio 2022에서 GLSL 문법 확인 및 구문 강조 (0) | 2025.02.18 |
| [OpenGL 008] glfw 키 2개 입력 방법 및 glfwSwapInterval (0) | 2025.02.15 |
| [OpenGL 007] 쉐이더 파일 생성 및 프로그램 수정 (0) | 2025.02.15 |
