Version: 2022.1
언어: 한국어
셰이더의 조건부
셰이더 배리언트

셰이더에서 브랜치

Branching is one way of introducing conditional behavior into shader code.

이 페이지에는 다음 기술에 관한 정보가 포함되어 있습니다.

셰이더 코드의 조건부와 언제 어떤 기술을 사용해야 하는지에 대한 일반적인 개요는 셰이더 코드의 조건부를 참조하십시오.

정적 브랜치

셰이더 프로그램이 컴파일 시 평가되는 조건부를 포함하는 경우 정적 브랜치를 사용합니다. 컴파일러는 사용되지 않은 브랜치에서 코드를 제외하므로 컴파일된 셰이더 프로그램에 나타나지 않습니다.

내부적으로 Unity는 셰이더 배리언트를 생성할 때 정적 브랜치를 사용합니다. 그러나 정적 브랜치 자체에는 셰이더 배리언트의 성능 단점이 없습니다.

정적 브랜치의 장점과 단점

정적 브랜치의 주요 장점은 런타임 성능에 부정적인 영향을 주지 않는다는 것입니다. 정적 브랜치의 주요 단점은 컴파일 시에만 사용할 수 있다는 것입니다.

정적 브랜치는 컴파일러가 셰이더 프로그램에서 불필요한 코드를 제외하는 것을 의미합니다. 그로 인해 필요한 코드만 포함하는 작고 전문화된 셰이더 프로그램이 생성됩니다. 정적 브랜치에는 런타임 성능 소모가 없습니다. 실제로 프로그램이 작을수록 로드 시간이 빨라지고 런타임 메모리 사용량이 낮아질 수 있습니다.

정적 브랜치를 사용하려면 컴파일 시 조건이 일정해야 합니다. 즉 런타임 시 다른 조건에 대한 코드를 실행하는 데 사용할 수 없습니다.

정적 브랜치를 사용하는 방법

다음과 같은 방법으로 셰이더에서 정적 브랜치를 사용할 수 있습니다.

  • 직접 코딩한 셰이더에서는 다음을 사용합니다.
    • Use #if, #elif, #else, and #endif preprocessor directives, or #ifdef and #ifndef preprocessor directives to create static branches.
    • 컴파일 시간 상수 값을 평가하는 if 문을 사용합니다. if 문은 동적 브랜치에도 사용할 수 있지만 컴파일러는 컴파일 시간 상수 값을 감지하고 대신 정적 브랜치를 만듭니다.
    • Unity는 정적 브랜치와 함께 사용할 수 있는 일부 컴파일 시간 상수에 대해 빌트인 매크로를 제공합니다.

참고: 정적 브랜치는 직접 코딩한 셰이더에서만 사용할 수 있습니다. 셰이더 그래프에서는 정적 브랜치를 만들 수 없습니다.

동적 브랜치

셰이더 프로그램이 런타임 시 평가되는 조건을 포함하는 경우 동적 브랜치를 사용합니다.

동적 브랜치에는 두 가지 타입이 있습니다. 균일한 변수에 기반한 동적 브랜치와 다른 런타임 값을 기반으로 하는 동적 브랜치입니다. 균일함을 기반으로 하는 브랜치가 전체 드로우 콜에 대해 균일한 값이 일정하기 때문에 일반적으로 더 효율적입니다.

You can use shader keywords for dynamic branching. This allows you to use C# scripts and the Material Inspector to configure runtime branching behavior for your shaders. This results is uniform-based branching; when you do this, Unity compiles the shader keywords as uniforms.

동적 브랜치의 장점과 단점

동적 브랜치의 주요 장점은 프로젝트의 셰이더 배리언트 수를 늘리지 않고도 런타임 시 조건부를 사용할 수 있다는 것입니다. 동적 브랜치의 주요 단점은 GPU 성능에 영항을 준다는 것입니다.

GPU 성능 영향은 하드웨어와 셰이더 코드에 따라 다릅니다. 이유는 다음과 같습니다.

  • 균일하지 않은 변수를 기반으로 하는 브랜치는 GPU가 같은 시간에 다른 작업을 수행함(따라서 병렬성이 중단됨)을 의미하거나 “브랜치를 평면화”하고 두 가지 브랜치에 대해 작업을 수행한 다음 한쪽 결과를 폐기하는 방식으로 병렬성을 유지해야 함을 의미합니다. 균일한 변수를 기반으로 하는 브랜치는 GPU가 브랜치를 평면화해야 함을 의미합니다. 이 두 가지 접근 방식 모두 GPU 성능을 저하시킵니다.
  • 모든 타입의 동적 브랜치에 대해 GPU는 최악의 경우 레지스터 공간을 할당해야 합니다. 한 브랜치가 다른 브랜치보다 훨씬 더 사용량이 많다면 GPU가 레지스터 공간을 낭비한다는 의미입니다. 이로 인해 셰이더 프로그램을 병렬로 호출하는 횟수가 줄어들어 성능이 저하될 수 있습니다.

일반적으로 코드 브랜치가 균일한 값으로 분기되고 두 브랜치의 워크로드가 거의 비슷하다면 GPU 성능에 미치는 영향은 작을 수 있습니다. 그러나 항상 애플리케이션을 프로파일하고 사례별로 장단점을 고려해야 합니다.

참고: 동적 브랜치는 또한 모든 조건에 대한 코드가 동일한 셰이더 프로그램으로 컴파일되기 때문에 대규모 셰이더 프로그램으로 이어질 수 있습니다. 그러나 이러한 대용량 파일의 로드 시간과 메모리 사용량에 미치는 영향은 일반적으로 셰이더 배리언트의 영향보다 덜 중요합니다.

셰이더에서 조건부를 사용하는 다른 방법과 사용 사례에 적합한 기술을 결정하는 방법에 대한 자세한 내용은 셰이더의 조건부를 참조하십시오.

동적 브랜치를 사용하는 방법

다음과 같은 방법으로 셰이더에서 동적 브랜치를 사용할 수 있습니다.

  • 직접 코딩한 셰이더에서는 다음을 사용합니다.
    • Optional: Set up shader keywords for use with with dynamic branching. You can use dynamic branching without shader keywords, but this provides simple set up and per-material configuration.
    • Use an if statement that evaluates the shader keywords (if used) or any other runtime state. You can use attributes to force the GPU to execute both branches, or to execute only one branch.
  • 셰이더 그래프에서는 브랜치 노드를 사용합니다. 이 방법은 항상 두 브랜치를 모두 실행합니다.
셰이더의 조건부
셰이더 배리언트