※ 이 글은 오가사와라 히로유키(小笠原博之) 씨가 블로그에 적은 글을 번역한 것입니다. 사정에 따라 예고없이 삭제될 수 있으므로 양해부탁드립니다.

OpenGL ES 2.0 Tegra2/3/4의 Fragment Shader와 동적루프

(원문 : OpenGL ES 2.0 Tegra2/3/4 の Fragment Shader と動的ループ)

Desktop GPU에서 Vertex Shader와 Pixel Shader의 사양이 완전히 통일된 것은 Direct3D 10의 ShaderModel 4.0 이후입니다. 그때까지는 쓸 수 있는 명령이나 Constant 영역, 레지스터 수, 프로그램 사이즈, 텍스처 명령등 여러가지 차이가 남아있었습니다.

Hardware의 Unified Shader화는 ATI의 Xbox360 GPU가 먼저 시작하였습니다. 이것이 지금의 Qualcomm Adreno로 이어집니다. 그 후 일반적인 Desktop PC용으로도 NVIDIA GeForce 8800 (G80)이 등장하여, 이후 Unified Shader Model이 당연해지게 됩니다.

OpenGL ES 2.0의 Shader 세대는 Direct3D 9의 Shader Model 3.0에 해당합니다만, 많은 Mobile GPU가 이미 Unified Shader화되어있습니다. 그렇기에 딱히 Vertex와 Fragment Shader의 성능차를 의식할 필요는 없었습니다.

그 중, Tegra2/3/4는 G70 베이스의 GPU로, Unified Shader화되기 전의 제한이 남아있는 드문 케이스입니다.

코멘트에서 Tegra의 Fragment Shader는 동적 루프를 쓸 수 없다는 지적을 받았기에 테스트해보았습니다.

// (1) 동적 루프
int loop= int( uniform_value );
for( int i= 0 ; i < loop ; i++ ){
   ...
}

↑루프 회수를 동적으로 구하는 경우, Vertex Shader는 통과하지만 Fragment Shader에서는 컴파일 시에 에러가 발생합니다.

예전에 적었듯 Uniform 배열의 index 접근↓(2)도 Tegra의 Fragment Shader에서는 에러가 뜹니다. 둘 다 Direct3D 9 세대의 제한이라 생각됩니다.

// (2) Uniform 배열
uniform vec4 src_color[30];
~
int index= int(tex_color.x);
vec4 color= src_color[ index ]; // Tegra의 Fragment Shader에서는 Error

Tegra 4에서도 마찬가지이므로, 기능은 대폭 확장되었지만 GPU의 베이스는 같다는 것을 알 수 있습니다. 참고로 Tegra와 같은 Discrete Type의 Shader Unit을 갖춘 Mali-400MP에서는 작동합니다.

	     Vertex Shader            Fragment Shader
	     동적Loop  Uniform배열    동적Loop  Uniform배열
-----------------------------------------------------------
Unified      ◯         ◯              ◯         ◯
Mali-400MP   ◯         ◯              ◯         ◯
Tegra2/3/4   ◯         ◯              ERROR     ERROR

하지만 Tegra에서도 동적 분기는 가능하기에, 실행시에 루프 횟수가 변동하는 경우에도 동등한 처리를 실현할 수는 있습니다.

// (3) Tegra용 동적분기에 의한 루프
for( int i= 0 ; i< 100 ; i++ ){
    if( i >= Loop ){
        break;
    }
    ~ 동적 루프에 해당하는 부분
}

이하 정리 (모두 Fragment Shader의 경우)

컴파일 시에 루프 횟수가 정해져 있지 않으면 에러.

// (4) 루프횟수 미정  -- Tegra에서 ERROR
for( int i= start ; i< end ; i++ ){
    ~
}

루프 범위가 정해저 있으면 컴파일 가능

// (5) 상한이 정해져있는 경우 -- Tegra에서도 OK
for( int i= 0 ; i< 100 ; i++ ){
    if( i >= start && i < end ){
        ~ 동적 루프에 해당하는 부분
    }
}

아마도 아래와 같이 전개되지 않을까 생각됩니다.

i= 0;
if( i >= start && i < end ){
    ~
}
i= 1;
if( i >= start && i < end ){
    ~
}

~

i= 99;
if( i >= start && i < end ){
    ~
}

Tegra K1 이후는 ShaderModel 5.0 세대의 GPU core가 되므로 이런 하드웨어적 제한은 없어질 것입니다.

관련글

※ 이 글은 오가사와라 히로유키(小笠原博之) 씨가 블로그에 적은 글을 번역한 것입니다. 사정에 따라 예고없이 삭제될 수 있으므로 양해부탁드립니다.

OpenGL ES 2.0 Adreno 330, Tegra 4의 GPU 속도

(원문 : OpenGL ES 2.0 Adreno 330, Tegra 4 の GPU 速度)

벤치마크 결과를 갱신했습니다.

Android 4.1 이후 및 대응하는 디바이스에서는 SwapInterval을 0으로 변경해서 60fps 이상 나옵니다. (관련글)

GPU            SoC   CPU clock OS    Screen     fps       pix/sec
---------------------------------------------------------------------
Adreno 330     MSM8974 2.2GHz  A4.2  1920x1200  71.98fps   165.8M
Adreno 320(64) APQ8064 1.5GHz  A4.4  1920x1104  40.97fps    86.8M
Mali-T604     Exynos5D 1.7GHz  A4.4  2560x1504  20.73fps    79.8M
ULP GeForce(72) Tegra4 1.8GHz  A4.3   1126x800  44.58fps    43.4M
ULP GeForce(12) Tegra3 1.2GHz  A4.4   1280x752  15.70fps    15.0M (*1)

*1: Shadow Map 없음, 16bit depth

Adreno 330은 예상 이상으로 빨라서, Adreno 320과 비교해도 약 2배 정도의 속도를 냅니다. 드디어 가장 부하가 높은 설정에서도 Full HD(1920x1200)에서 60fps를 넘게 되었습니다.

그에 비해 Tegra 4는 그다지 속도가 늘지 않았습니다. 부하를 낮춰도 속도가 올라가지 않으므로, SwapInterval 설정이 효과가 없던지 뭔가 문제가 발생했을 가능성이 있습니다.

그 대신 Tegra 3에서 생략되었던 여러 extension을 지원하여 렌더링 결과가 다른 GPU와 거의 일치하게 되었습니다.

특히 GL_EXT_shadow_samplers는 그냥 Hardware ShadowMap이 아니라 PCF에 제대로 Bi-linear Filter도 걸립니다. GL_EXT_shadow_samplers는 OpenGL ES 3.0 이후의 디바이스는 전부 대응하고 있지만, 반드시 Filter가 걸리는 것은 아닌 듯 합니다. 아래는 몇가지 테스트한 결과입니다.

                               depth-tex sh-samplers PCF Filter
----------------------------------------------------------------
8064 Adreno 320 OpenGL ES 3.0      ◎        ◎      ◎   --
8064 Adreno 320 OpenGL ES 2.0      ◎        --      --   --
Mali-T604       OpenGL ES 3.0      ◎        ◎      ◎   ◎
Tegra 4         OpenGL ES 2.0      ◎        ◎      ◎   ◎
Tegra 3         OpenGL ES 2.0      --        --      --   --
iOS PVR 543MP3  OpenGL ES 2.0      ◎        ◎      ◎   ◎
Vivante GC4000  OpenGL ES 2.0      ◎        --      --   --
Mali-400MP4     OpenGL ES 2.0      ◎        --      --   --
PowerVR SGX540  OpenGL ES 2.0      ◎        --      --   --

이쪽에 관해서는 조금 더 자세하게 조사할 생각입니다. 또 Tegra4의 Extension 상세사항은 다음 페이지에 추가했습니다.

관련 페이지

+ Recent posts