프로그래밍 2017. 12. 8. 12:09
728x90


쉐이더 ( HLSL ) - 정적분기



HLSL 흐름제어


정적분기

조건명령

정적루프

동적분기

동적루프



동적분기는 변수안에 내재된 상태를  비교하는데, 이것은

비교가 실행중에 각각의 버텍스 또는 픽셀별로 일어난다는 것이다

실행효율은 (분기의 비용 + 분기에 나눠진 명령어들의 비용)

쉐이더모델3이상 지원



정적분기는 bool 쉐이더 상수에 기초해서, 쉐이더 코드의 블록을 on/off 하는게 가능하다

이것은 현재 렌더링되는 오브젝트 타입에 따라서, 

코드패스를 활성화 비활성화 하는 편리한 방법


draw 호출동안에 현재 쉐이더에서 지원하기를 원하는 특징을 결정할수 있고,

필요로 하는 것을 위해서, boolean 플래그를 셋팅하면 된다

boolean 상수에 의해서 비활성화된 어떤 구문이라도 쉐이더 실행동안에는 무시된다


정적분기는 컴파일할때 구성된다

따라서, 실행시의 동적인 오버헤드가 없다

(안정적인 프레임을 보장)




요즘 쉐이더 최적화 작업을 하면서,

무분별하게 사용하던, if 문이 많은 밴드위드를 일으킨다는 것을 알게 되었다

(프레임이 급저하했다가, 다시 회복되는 현상)


하나의 vs, ps 에서 if 문으로 동적으로 변하는 것들을 처리하고 있었다면,

if 문을 최대한 없애고,

(약간의 계산이 추가된다면, 분기하지 말고, 그냥 통합해서 처리해 버리자, 

차라리 그게 낫다)


렌더링 타입에 따라,

정적 분기로 미리 vs, ps 를 나누어 두고 사용하는 것이

프레임 최적화에 도움이 된다



예제)


technique Tech_OrigEffect

{

    pass P0

    {

        VertexShader = compile vs_3_0 VS();

        PixelShader  = compile ps_3_0         PS_OrigEffect( false, false );

    }

}


technique Tech_OrigEffect_VF

{

    pass P0

    {

        VertexShader = compile vs_3_0 VS();

        PixelShader  = compile ps_3_0         PS_OrigEffect( true, false );

    }

}


technique Tech_OrigEffect_VL

{

    pass P0

    {

        VertexShader = compile vs_3_0 VS();

        PixelShader  = compile ps_3_0         PS_OrigEffect( false, true );

    }

}


technique Tech_OrigEffect_VF_VL

{

    pass P0

    {

        VertexShader = compile vs_3_0 VS();

        PixelShader  = compile ps_3_0         PS_OrigEffect( true, true );

    }

}



//uniform = const 

float4 PS_OrigEffect( VS_OUTPUT _In, uniform bool _ufbVF, uniform bool _ufbVL ) : COLOR

{

//_ufbVF - 볼륨포그를 계산할것인가?

  //_ufbVL - 볼류메트릭 라이팅을 계산할 것인가?

float4 Out = Calc_PostColor( _In.uv, _ufbVF, _ufbVL );


//bloom

Out.rgb += tex2D( Samp_Texture_Bloom, _In.uv ).rgb;


//

Out.rgb *= _In.diff;


//change gamma

Out.rgb = ( (int)_vOrigEffectVal.x != 1 ) ? pow( Out.rgb, _vOrigEffectVal.x ) :         Out.rgb;

//if 대신에 ?: 문으로 대체


return Out;

}



이전에는

볼륨포그와 볼륨라이트 계산을 하나의 ps 코드에 모두 넣어두고

if( bool 변수 ) 로 체크했었는데, 이 부분이 많은 오버헤드를 일으키고 있었다


따라서,

정적분기로 Tech 를, 미리 나누어 두고,

소스코드에서는 게임 상태에 따라, 실시간으로 Tech 를 변경해서 사용하도록 수정하였다


정적분기를 사용할때, 귀찮은 점은

특정 렌더링 계산이 추가될때,

Tech 역시, 추가해 주어야 한다는 것인데,


2개까지는 경우의 수가 4개이니,

그럭저럭 나눌만 하지만,


3개, 4개가 되면, 아주 복잡해 진다는 것이다

모든 경우에 대해, 미리 Tech 를 만들어 두어야 하니...


뭔가 더 좋은 방법없을까?


아시는 분은 리플좀 부탁드려요~




728x90
posted by BK dddDang
: