2013-07-25 1 views
5

가능한 경우 쉐이더 모범 사례에서 avoid branching으로, 특히 쉐이더 내에서 계산 된 값으로 분기하는 것으로 Apple은 말합니다. 그래서 if 문을 내장 된 clamp() 함수로 대체했습니다. 제 질문은 clamp(), min()max()이 더 효율적일까요 아니면 단지 if 블록으로 확장되는 편의성 (즉 매크로) 기능일까요?조건부에 대한 OpenGL ES 모범 사례

구현에 따라 달라질 수 있습니다. 어쨌든 함수는 분명히 명확하고 명확한 의도를 내포합니다. 컴파일러 과 함께 할 수 있습니다.

+2

나는 당신의 마지막 문장이 이미 아주 잘 대답한다고 생각합니다. 훨씬 간소화 된 것 외에도 빠른 하드웨어 명령어로 구현 될 가능성이 보통 "if"보다 더 높습니다. 그리고이 일반적인 제안 (별도로 충분해야 함)을 제외하고 실제로는 특별한 하드웨어 지침이나 조건부 할당을 사용하고 'if'를 래핑하는 기능이 아닌 것입니다. –

답변

9

역사적으로 말하면 GPU는 임의 조건부 분기를 지원 한 것보다 훨씬 오래 오래 MINMAX과 같은 조각 별 명령어를 지원합니다. 데스크탑 OpenGL에서이 중 하나의 예는 분기를 지원하지 않는다는 명시 적으로 명시된 GL_ARB_fragment_program 확장 (현재 GLSL로 대체 됨)이지만 MINMAX 및 기타 조건부 명령어에 대한 지침을 제공합니다.

min(), max()clamp()이 쉐이더에 얼마나 일반적인지를 고려하면 모든 GPU가 여전히 이러한 작업을위한 전용 하드웨어를 가지고 있다고 확신 할 수 있습니다. 이것은 구현이 코드를 최적화 할 수 있지만 코드를 최적화 할 수 있기 때문에 사양에 의해 보장되는 것은 아니지만 실제 환경에서는 자신의 롤링보다는 내장 된 GLSL 함수를 사용해야합니다.

유일한 예외는 많은 양의 추가 조각 처리를 피하기 위해 조건을 사용하고있는 경우입니다. 어느 지점에서 지점의 비용은 지점의 모든 코드를 실행하는 데 드는 비용보다 적지 만 여기서 균형은 하드웨어에 따라 크게 달라 지므로 벤치 마크를 통해 해당 코드가 실제로 응용 프로그램에서 도움이되는지 확인해야합니다. 대상 하드웨어. 낭비 노력 NDotL을하는 경우가 많이

void main() { 
    vec3 N = ...; 
    vec3 L = ...; 
    float NDotL = dot(N, L); 
    if (NDotL > 0.0) 
    { 
     // Lots of very intensive code for an awesome shadowing algorithm that we 
     // want to avoid wasting time on if the fragment is facing away from the light 
    } 
} 

그냥 항상에만 NDotL하여 최종 그림자 기간을 곱하면 각 조각에 그림자 코드를 처리 한 후 NDotL 0-1에와 클램핑한다 : 여기 물건의 종류 말의 원래는 < = 0 이었으므로 이론적으로 분기를 통해이 오버 헤드를 피할 수 있습니다. 이런 종류의 일이 항상 성과를 거두지는 못하는 이유는 하드웨어가 셰이더 분기를 구현하는 방법에 크게 의존하기 때문입니다.

+0

우수한 리뷰. 나는'MIN'과'MAX'가 일반적인'if' 블록보다 먼저 나온 것을 깨달았어야했는데, 이것들에 대한 하드웨어 지원에 대해 확신합니다. 많은 감사합니다! –

+0

내가 언급해야 할 것은, 일부 GPU는 표준을 존중하지 않으며 전혀 분기를 구현하지 않는다는 것입니다. 나는 삼성의 Galaxy Tab 시리즈를 발견했다. 그들은 아무런 메시지도없이 단지 침묵의 충돌 만합니다. –