참고 : blog.hybrid3d.dev/2020-12-21-reason-for-slow-of-if-statement-in-shader
쉐이더에서 IF 문이 느린 이유
개요 쉐이더에서 if 문이 성능에 좋지 않다는 것은 프로그래머가 아니더라도 많이들 알고 있는 사실이다. 중요한 것은 단순히 if 문이 느리다는 것이 아니다, if 문이 필요해서 if 문을 쓰는 것인
blog.hybrid3d.dev
참고 : docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-if
if Statement - Win32 apps
Conditionally execute a series of statements, based on the evaluation of the conditional expression.
docs.microsoft.com
| half4 frag(VertexOutput i) : SV_Target { float4 col = i.uv.x; return color; } |


| half4 frag(VertexOutput i) : SV_Target { float4 col = col.rgba; if(i.uv.y > 0.5) { col = pow(i.uv.x, 2.2) ; } else { col = i.uv.x; } return color; } |


삼항연산자로 변환하면 아래와 같다. 이는 ASE로 변환해도 내용은 순서만 살짝 다르고 똑같다.
| half4 frag(VertexOutput i) : SV_Target { float4 col = i.uv.y > 0.5 ? pow(i.uv.x, 2.2) : i.uv.x; // 조건문 ? 참일때 실행값 : 거짓일때 실행값 ; return color; } |
왜 if문이 문제일까?
GPU는 SIMD(Single Instruction Multiple Data) 구조라서, 워프(Warp) 내의 모든 쓰레드가 같은 명령어를 동시에 실행해야 한다. 그런데 if 분기가 발생하면 일부 쓰레드는 대기해야(branch divergence)하면 이는 성능 손실로 이어지며 그래서 분기가 많은 쉐이더는 속도가 급격히 떨어질 수 있다. 삼항연산자 ?:는 컴파일러가 한 라인 안에서 아래와 같이 수식으로 해결할 수 있따.
float result = cond ? a : b; |
result = lerp(b, a, cond); // cond가 1이면 a, 0이면 b |
early return 패턴처럼 작성도 가능하다.
float CalculateSomething(float x) { if (x < 0.0) return 0.0; return x * x; } |
- Shader Model 2.0 이하 분기 최적화 거의 안 됨, 분기=무조건 느림
- Shader Model 4.0+ 일부 하드웨어는 Dynamic Branch 최적화 지원
- 모바일 GPU (Mali, Adreno) 분기 비용 매우 큼, 최대한 branchless 설계 권장(요즘엔 모르겠음)
'Technical Report > Unity' 카테고리의 다른 글
| URP Shader BlinnPhong with Normal mapping (0) | 2021.07.08 |
|---|---|
| URP Shader coding guide Basic term (4) | 2021.05.01 |
| 2D Signed Distance Field Basics (0) | 2021.02.10 |
| Shader Graph Custom Shader function (0) | 2020.02.15 |
| Shader에서 Linear <-> sRGB 변환 함수 (0) | 2020.02.14 |