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

Desktop GPU와 OpenGL ES 3.1 API

(원문 : Desktop GPU と OpenGL ES 3.1 API)

OpenGL ES는 Mobile등에서 사용되는 API지만, Desktop 대상 OpenGL에도 적극적으로 이식되어 호환성을 가지게 되었습니다. OpenGL 4.5에서는 GL_ARB_ES3_1_compatibility를 지원하여, OpenGL ES 3.1 API로도 쓸 수 있습니다.

2015/06/25 현재 Windows에서의 대응상황 (beta driver 포함)

Windows           Desktop API   Mobile API
-------------------------------------------------------------
GeForce           OpenGL 4.5    OpenGL ES 3.1 AEP
RADEON            OpenGL 4.5    OpenGL ES 3.1
Intel 4000 (Gen7) OpenGL 4.0    OpenGL ES 3.1    IvyBridge세대
Intel 4600 (7.5)  OpenGL 4.3    OpenGL ES 3.1    Haswell세대

Intel과 GeForce는 OpenGL ES 3.1 Context를 다시 만들 필요가 있습니다. RADEON의 경우는 OpenGL 4.5 Context 그대로 사용합니다. Desktop GPU에서 OpenGL ES를 사용하는 방법에 대해서는 아래 페이지에 정리해두었습니다.

Intel HD Graphics (D3D11 세대)는 OpenGL 4.5에 대응하지 않지만, 새 드라이버에서 OpenGL ES 3.1에 대응합니다. 구체적으로는 Ivy Bridge 세대의 Intel HD Graphics 4000/2500 이후로, BayTrail의 HD Graphics도 포함됩니다.

Intel HD Graphics 4000 (Ivy Bridge) Windows 8.1 x64

GL_VERSION: OpenGL ES 3.1 - Build 10.18.10.4226
GL_RENDERER: Intel(R) HD Graphics 4000
GL_VENDOR: Intel
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.1 - Build 10.18.10.4226
Intel HD Graphics (BayTrail-T Atom Z3740) Windows 10 x86

GL_VERSION: OpenGL ES 3.1 - Build 10.18.10.3993
GL_RENDERER: Intel(R) HD Graphics
GL_VENDOR: Intel
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.1 - Build 10.18.10.3993
Intel HD Graphics 4600 (Haswell) Windows 10 x64

GL_VERSION: OpenGL ES 3.1 - Build 10.18.15.4235
GL_RENDERER: Intel(R) HD Graphics 4600
GL_VENDOR: Intel
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.10 - Build 10.18.15.4235

GeForce처럼 GL_ANDROID_extension_pack_es31a (AEP)는 없습니다만, Tessellator/GeometryShader 등 일부 기능은 독자적으로 대응이 이루어져있습니다. OpenGL ES 3.1 context에서는 다음 extension이 포함되어 있다는 것을 알 수 있습니다.

GL_INTEL_tessellation
GL_INTEL_geometry_shader

GeForce는 OpenGL ES 3.1 context로 AEP를 지원합니다. 다만 GPU에 따라서는 AEP에서 필요한 일부기능(ASTC Texture)을 소프트웨어로 에뮬레이션하는 것 같습니다. NVIDIA는 Mobile 용으로 GLES Emulator Library를 릴리즈하지 않으므로 그것을 겸하고 있는 것일지도 모릅니다.

RADEON는 OpenGL 4.x 그대로이므로 딱히 기능제한은 없습니다. 따라서 언제든지 GLES API로 OpenGL 4.x에 해당하는 기능을 쓸 수 있습니다.

GPU 별 상세는 아래 페이지에 실어두었습니다. 가능한 범위에서 각 OpenGL ES 3.1 context의 결과도 포함되어있습니다.

관련 글

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

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가 되므로 이런 하드웨어적 제한은 없어질 것입니다.

관련글

+ Recent posts