"눈이 나쁘면 안경을 쓴댔으니 모자란 너에겐 모자를 씌워주마" – 김케장 / 동전주머니엔 동전이 들었지

20160328
셰이더 자료형과 정밀도

원문

http://docs.unity3d.com/Manual/SL-DataTypesAndPrecision.html

내용이 추가되었는데 한국어가 없어서 번역해서 적어놓습니다. 오역이 있을 수 있습니다 ;ㅁ;

셰이더 자료형과 정밀도

유니티의 표준 셰이더 언어는 Cg/HLSL이며 일반 HLSL 자료형을 지원합니다. HLSL 자료형에 더불어 유니티는 특히 휴대기기 플랫폼을 더 잘 지원하는 몇몇 추가 자료형을 가지고 있습니다.

기본 자료형

셰이더 계산 대부분은 부동 소수점(C#같은 일반적인 프로그래밍 언어에 있는 float)으로 끝납니다. float, half와 fixed(거기에 벡터/행렬 형식들을 포함, 예. half3과 float4x4)처럼 몇 종류의 부동 소수점 자료형이 제공됩니다. 이 자료형들은 정밀도(와 그로 인한 성능 또는 자원 사용)에 있어 차이가 있습니다.

float: 고정밀도

최고 정밀도 부동 소수점 값, 일반 프로그래밍 언어의 float과 같으며 대개 32비트입니다.

완전 실수(float) 정밀도는 일반적으로 전역(world) 공간 위치, 텍스처 좌표나 복잡 함수(삼각법, 지수승/거듭제곱 등등) 관련 스칼라 계산에 사용됩니다.

half: 중정밀도

중간 정밀도 부동 소수점. 대개 16비트(범위 -60000에서 +60000인 대략 세 자리 십진수 정밀도).

절반 정밀도는 짧은 벡터, 방향, 물체 공간 위치, 고 동적 범위(HDR) 색상 사용에 효과적입니다.

fixed: 저정밀도

낮은 정밀도, 고정 소수점. -2.0에서 +2.0의 범위에 1/256 정밀도를 가지며 대개 11비트.

고정 정밀도는 (일반 텍스처에 일반적으로 들어있는)일반 색상(게슈탈트 붕괴)과 여기에 적용하는 간단한 계산에 사용하면 효과적입니다.

정수 자료형

정수(int 자료형)는 반복 횟수나 배열 첨자로 대개 사용되며 이런 목적으로는 여러 플랫폼에서 보통은 잘 작동합니다.

플랫폼에 따라서는 정수 자료형은 GPU에서 실제로는 지원하지 않을 수 있습니다. 예로 Direct3D 9와 OpenGL ES 2.0 GPU는 부동 소수점 자료형으로만 연산하며 (비트나 논리 연산 포함해서) 단순해 보이는 정수 표현은 꽤 복잡한 부동 소수점 수학 명령어로 에뮬레이팅 될 수 있습니다.

Direct3D 11, OpenGL ES 3, Metal과 다른 현역 플랫폼은 정수 자료형을 제대로 지원하기 때문에, 비트 밀기, 비트 마스크 등등을 사용 가능합니다. 실수(gotcha, 문법적으로는 문제가 없지만, 작성자 의도와 다르게 작동)를 많이 범하지 않고 원하는 대로 작동합니다.

복합 벡터/행렬 자료형

HLSL은 기본 자료형으로 구성된 내장 벡터와 행렬 자료형을 포함합니다. 예로 float3은 .x, .y, .z 요소로 된 삼차원 벡터이며 half4는 중정밀도 (.x, .y, .z, .w 요소로 된) 사차원 벡터입니다. 벡터는 이를 대신해서 색상으로 동작하게 할 때 유용한 .r, .g, .b, .a 요소를 첨자로 사용할 수 있습니다.

행렬 자료형도 같은 방식으로 내장되어 있습니다. 예를 들어 float4x4는 4×4 변환 행렬입니다. 몇몇 플랫폼 중 특히나 OpenGL ES 2.0은 정방 행렬만 지원한다는 점을 유의하세요.

텍스처/추출기(Sampler) 자료형

HLSL 코드로 텍스처를 정의 하려면 일반적으로 다음과 같이 합니다.

sampler2D _MainTex;
samplerCUBE _Cubemap;

휴대기기 플랫폼에서는 위의 코드는 “저정밀도 추출기”로 번역됩니다. 즉, 텍스처는 저정밀도 정보를 갖게 됩니다. 만약 사용하는 텍스처가 HDR 색상을 가지고 있고, 이를 절반 정밀도 추출기로 사용하고 싶다면 다음과 같이 합니다.

sampler2D_half _MainTex;
samplerCUBE_half _Cubemap;

또는 텍스처가 완전 실수 정밀도 정보(예. 깊이 텍스처)를 가지고 있다면 완전 정밀도 추출기를 사용하세요.

sampler2D_float _MainTex;
samplerCUBE_float _Cubemap;

정밀도, 하드웨어 지원과 성능

float/half/fixed 자료형을 사용하는 데 있어 문제 중 하나는 모든 PC GPU는 항상 고정밀도라는 것입니다. 다시 말해서 모든 PC(윈도우즈/맥/리눅스) GPU는 셰이더에 float, half 또는 fixed 자료형 중 뭘 사용하든지 간에 완전히 아무 상관 없다는 것입니다. 뭘 사용하든 항상 32비트 부동 소수점 최고 정밀도로 계산합니다.

half와 fixed 자료형은 몇몇 상황에서 성능, 제한과 비용이 주로 발생하는 이런 타입을 사용하는 휴대기기 GPU를 목표로 할 때만 의미가 있지만, 정확도 / 숫자 관련 문제가 발생하는지 안 하는지 보기 위해 휴대기기에서 셰이더를 검사할 때에는 유의해야 합니다.

휴대기기 GPU도 GPU군(family)에 따라 지원하는 정밀도가 다릅니다. 각각의 휴대기기 GPU군이 각각 부동 소수점 자료형을 어떻게 다루는지는 다음 개요를 봐주세요. (숫자는 자료형을 몇 비트로 사용하는지 나타냅니다.)

GPU군(family) floathalffixed
PowerVR Series 6/7 321616
PowerVR SGX 5xx321611
Qualcomm Adreno 4xx/3xx 321616
Qualcomm Adreno 2xx 정점 32 픽셀 243232
ARM Mali T6xx/7xx 321611
ARM Mali 400/450 정점 32 픽셀 243232
NVIDIA X1 321616
NVIDIA K1 323232
NVIDIA Tegra 3/4 321616

보다시피, 대부분의 현역 휴대기기 GPU는 실제로 32비트 수(float 형으로 사용)나 16비트 수(half와 fixed 형으로 사용)만 지원합니다.

몇몇 구형 GPU는 표에 나와 있는 것처럼 정점 셰이더와 픽셀 셰이더 계산에 다른 정밀도를 가집니다.

낮은 정밀도를 사용하면 향상된 GPU 레지스터 할당이나 확실히 더 낮은 정밀도 수학 연산에 쓰이는 특수 “빠른 경로” 실행 단위 때문에 대개 더 빨라집니다. 실제로 성능 향상이 없을 때도 낮은 정밀도를 사용하면 GPU가 대개 더 적은 자원을 사용하게 되어 배터리 사용 시간을 더 늘릴 수 있습니다.

대개 일반적으로 위치와 텍스처 좌표를 제외한 모든 것을 half 정밀도로 시작합니다. half 정밀도가 계산하는 데 있어 충분하지 않은 경우에만 정밀도를 올립니다.

무한, NaN과 다른 특수 부동 소수점 값 지원

정밀도처럼 계산에 사용되는 것은 어떤 GPU군(특히나 휴대기기)에서 돌아가는지에 따라 달라지며 그래서 특수한 부동 소수점 값을 지원합니다.

(일반적으로 2006년 이후 생산된) Direct3D 10을 지원하는 모든 PC GPU상에서 부동 숫자는 CPU상의 일반적 프로그래밍 언어에서 작동하는 것과 정확히 같게 동작해야 한다고 명시된 IEEE 754 부동 소수점 표준을 아주 잘 지원합니다.

하지만 휴대기기상에서는 명확하지 않은 상황입니다. 일부 GPU상에서 영(0)을 영으로 나누는 것은 PC GPU나 CPU처럼 NaN(“not a number”, 숫자가 아님)을 결과로 내며 일부 다른 GPU상에서는 무한, 영 또는 다른 명시되지 않은 값을 냅니다. 목표로 하는 기기상에서 셰이더를 확실히 검사하세요!

댓글 남기기 | 타닥타닥

댓글 남기기

* 표시된 곳은 반드시 입력해주세요