GLSL에서 분기를 일으키는 원인은 GPU 모델 및 OpenGL 드라이버 버전에 따라 다릅니다.
대부분의 GPU는 분기 비용이없는 "두 값 중 하나를 선택하십시오"형식의 작업 인 것 같습니다.
n = (a==b) ? x : y;
때로는 다음과 같은 것들도 있습니다 :
if(a==b) {
n = x;
m = y;
} else {
n = y;
m = x;
}
분기 벌금없이 몇 가지 선택 값 작업으로 축소됩니다.
일부 GPU / 드라이버는 두 값 사이의 비교 연산자에 약간의 페널티가 있지만 0에 비해 비교 작업이 더 빠릅니다.
더 빠른 곳 :
gl_FragColor.xyz = ((tmp1 - tmp2) != vec3(0.0)) ? E : tmp1;
(tmp1 != tmp2)
직접 비교 하는 것이 아니라 이것은 GPU와 드라이버에 따라 매우 다르므로 매우 구체적인 GPU를 타겟팅하지 않는 한 비교 연산을 사용하지 않는 것이 좋습니다. 다른 드라이버가 더 긴 형식에 문제가있을 수 있으므로 OpenGL 드라이버에 최적화 작업을 남겨 두십시오. 더 간단하고 읽기 쉬운 방법으로 더 빨라집니다.
"분기"가 항상 나쁜 것은 아닙니다. 예를 들어 OpenPandora에서 사용되는 SGX530 GPU에서이 scale2x 셰이더 (30ms)는 다음과 같습니다.
lowp vec3 E = texture2D(s_texture0, v_texCoord[0]).xyz;
lowp vec3 D = texture2D(s_texture0, v_texCoord[1]).xyz;
lowp vec3 F = texture2D(s_texture0, v_texCoord[2]).xyz;
lowp vec3 H = texture2D(s_texture0, v_texCoord[3]).xyz;
lowp vec3 B = texture2D(s_texture0, v_texCoord[4]).xyz;
if ((D - F) * (H - B) == vec3(0.0)) {
gl_FragColor.xyz = E;
} else {
lowp vec2 p = fract(pos);
lowp vec3 tmp1 = p.x < 0.5 ? D : F;
lowp vec3 tmp2 = p.y < 0.5 ? H : B;
gl_FragColor.xyz = ((tmp1 - tmp2) != vec3(0.0)) ? E : tmp1;
}
이 동등한 쉐이더 (80ms)보다 극적으로 빠릅니다.
lowp vec3 E = texture2D(s_texture0, v_texCoord[0]).xyz;
lowp vec3 D = texture2D(s_texture0, v_texCoord[1]).xyz;
lowp vec3 F = texture2D(s_texture0, v_texCoord[2]).xyz;
lowp vec3 H = texture2D(s_texture0, v_texCoord[3]).xyz;
lowp vec3 B = texture2D(s_texture0, v_texCoord[4]).xyz;
lowp vec2 p = fract(pos);
lowp vec3 tmp1 = p.x < 0.5 ? D : F;
lowp vec3 tmp2 = p.y < 0.5 ? H : B;
lowp vec3 tmp3 = D == F || H == B ? E : tmp1;
gl_FragColor.xyz = tmp1 == tmp2 ? tmp3 : E;
벤치 마크 할 때까지 특정 GLSL 컴파일러 또는 특정 GPU의 성능을 미리 알 수 없습니다.
지점을 추가하기 위해 (이 부분에 대해 실제 타이밍 번호와 셰이더 코드가 없어도) 현재 일반 테스트 하드웨어로 사용합니다.
- 인텔 HD 그래픽 3000
- 인텔 HD 405 그래픽
- nVidia GTX 560M
- 엔비디아 GTX 960
- AMD 라데온 R7 260X
- 엔비디아 GTX 1050
테스트 할 다양한 다른 일반적인 GPU 모델입니다.
Windows, Linux 독점 및 Linux 오픈 소스 OpenGL 및 OpenCL 드라이버로 각각 테스트합니다.
그리고 하나의 특정 GPU / 드라이버 콤보에 대해 GLSL 쉐이더 (위의 SGX530 예제에서와 같이) 또는 OpenCL 작업을 미세 최적화하려고 할 때마다 다른 GPU / 드라이버 중 하나 이상의 성능이 동일하게 저하됩니다.
따라서 높은 수준의 수학적 복잡성을 명확하게 줄이고 (예 : 5 개의 동일한 부분을 단일 왕복으로 변환하고 5 개의 곱셈으로 변환) 텍스처 룩업 / 대역폭을 줄이는 것 외에는 시간 낭비 일 가능성이 높습니다.
모든 GPU는 다른 GPU와 너무 다릅니다.
특정 GPU가있는 (a) 게임 콘솔에서 특별히 작업하는 경우에는 다른 이야기가 될 것입니다.
이것의 다른 (작은 게임 개발자에게는 중요하지 않지만 여전히 주목할만한) 측면은 컴퓨터 GPU 드라이버가 언젠가 자동으로 쉐이더를 ( 그 게임이 충분히 유명 해지면 ) 특정 GPU에 최적화 된 커스텀 재 작성된 것으로 대체 할 수 있다는 것입니다. 모든 것이 당신을 위해 일하는 것.
벤치 마크로 자주 사용되는 인기있는 게임에 대해이 작업을 수행합니다.
또는 플레이어에게 셰이더에 대한 액세스 권한을 부여하여 쉽게 직접 편집 할 수 있도록하는 경우 일부 사용자는 자신의 이익을 위해 몇 가지 추가 FPS를 압박 할 수 있습니다.
예를 들어 Oblivion을 위해 팬이 만든 셰이더 및 텍스처 팩이있어 거의 재생이 불가능한 하드웨어에서 프레임 속도를 크게 높일 수 있습니다.
마지막으로, 셰이더가 복잡해지면 게임이 거의 완료되고 다른 하드웨어에서 테스트를 시작하면 다양한 GPU에서 작동하도록 셰이더를 수정하는 것만으로 바쁠 것입니다. 그 정도로 최적화 할 시간이 있습니다