Unity 검색

새로운 Caching Shader Preprocessor를 통한 빌드 속도 단축(실험 기능)

2020년 5월 6일 테크놀로지 | 5 분 소요
다루는 주제
공유

Is this article helpful for you?

Thank you for your feedback!

셰이더 컴파일은 여러 단계를 거쳐야 하는 긴 과정이며 그 첫 번째 단계에서 셰이더 소스를 프리프로세싱합니다. Unity 2020.1 베타에는 이 컴파일 단계를 수행하기 위한 새로운 커스텀 솔루션인 Caching Shader Preprocessor가 도입되었습니다. 플랫폼 컴파일러의 프리프로세서보다 최대 25% 더 빠르고, C 표준을 엄격히 따르며 새로운 기능을 제공합니다.

Unity를 사용하다 보면 직·간접적으로 셰이더를 다루게 됩니다. 셰이더는 GPU에서 실행되는 프로그램으로, 오브젝트가 화면에 렌더링되는 방식을 결정합니다. 예를 들어, 씬에 점 광원이 추가되면 그에 반응해야 하는 오브젝트는 점 광원 처리 방법을 정의하는 다른 셰이더 배리언트를 사용합니다.

Unity 에디터는 새로운 셰이더 배리언트가 사용될 때마다 이를 컴파일해야 하며, 타겟 디바이스에서 실행할 애플리케이션을 빌드할 때도 필요한 셰이더를 모두 컴파일해야 합니다.

에디터 설정에서 Shader Compilation 섹션에 Caching Shader Preprocessor를 활성화 또는 비활성화하는 체크박스가 있습니다.

이번 포스팅에서는 셰이더를 작성할 때 유용한 기술 정보를 소개해 드립니다.

빠르고 효율적인 빌드

새로운 프리프로세서는 중간 프리프로세싱 데이터를 캐시 처리하여 셰이더 임포트 및 컴파일 시간을 단축합니다. 이 캐싱을 사용하면 콘텐츠가 변경되지 않는 한 에디터에서 include 파일을 파싱할 필요가 없으며, 동일한 셰이더의 여러 배리언트를 더욱 효율적으로 컴파일할 수 있습니다. 새로운 프리프로세서는 프로젝트 내 셰이더가 대규모 공통 include 파일 집합을 사용할 때 가장 빛을 발합니다.

기능 통합

각각의 셰이더 컴파일러의 백 엔드에는 자체 프리프로세서가 제공됩니다. 컴파일러를 실행하기 전에 표준화된 커스텀 프리프로세싱 레이어를 실행하면 셰이더 코드가 현재 또는 이후에 사용되는 모든 컴파일러의 백 엔드와 호환되므로 Unity 버전 간의 프로젝트 업그레이드가 용이해집니다.

이제 셰이더 임포트 시 이전에 사용되었던 일반 텍스트 파싱 솔루션 대신 동일한 프리프로세서를 사용하여 셰이더 컴파일 파라미터(#pragma 지시문)를 확인합니다. 따라서 조건부 #pragma 지시문 선택 및 해당 지시문을 include 파일에 포함하는 기능 등 새로운 추가 기능을 제공할 수 있게 되었습니다.

새로운 기능

이제 셰이더 인스펙터에 'Preprocess only' 체크박스가 표시되어 컴파일된 셰이더 코드와 프리프로세싱을 거친 셰이더 소스 표시 간 전환이 가능합니다. 이 기능은 모든 셰이더 개발자에게 매우 유용하며 셰이더 디버깅을 용이하게 합니다.

include 파일의 셰이더 컴파일 파라미터
새로운 프리프로세서 지시문 #include_with_pragmas를 도입하여 이제 셰이더 개발자가 include 파일에서 컴파일 설정을 제어하는 #pragma 지시문을 추가할 수 있습니다. 이 지시문은 정규 #include 지시문 역할을 하지만 셰이더 임포트 시에 무시되지 않습니다.

이를 통해 셰이더 임포트 시간이 최소화되며, 이러한 구분이 없으면 셰이더에 포함된 모든 파일을 프리프로세싱해야 합니다.

이전 셰이더 임포트 경로는 새로운 지시문을 무시합니다.

조건부 셰이더 컴파일 지시문 선택
셰이더 임포트 중에 프리프로세서를 실행하면 프리프로세서 조건문에서 셰이더 컴파일을 제어하는 #pragma 지시문을 래핑할 수 있습니다.

모든 조건문이 #pragma 선택에 영향을 줄 수 있는 것은 아닙니다. 프리프로세서는 조건식에 대한 인수의 출처를 감지하며, 따라서 재귀를 방지하고 셰이더 컴파일 파이프라인에 대한 침범을 최소화할 수 있습니다. 조건문은 제네릭 매크로 정의(Unity 버전 또는 UNITY_OLD_PREPROCESSOR 매크로), 사용자 매크로 정의 또는 빌드 타겟에 종속되어 다른 방식으로 구성할 수 없는 플랫폼 키워드에 종속된 경우에만 #pragma 지시문 보고에 영향을 줍니다. 후자의 예로는 SHADER_API_DESKTOP, SHADER_API_MOBILE, UNITY_NO_CUBEMAP_ARRAY, UNITY_FRAMEBUFFER_FETCH_AVAILABLE, UNITY_USE_NATIVE_HDR, UNITY_NO_RGBM뿐만 아니라 콘솔 SHADER_API_ <CONSOLE> 키워드가 있습니다. 이러한 키워드는 빌드 타겟에만 종속됩니다. 참고로 #pragma multi_compile 또는 #pragma shader_feature 지시문으로 지정된 사용자 키워드는 '사용자 매크로 정의'에 포함되지 않습니다.

유효한 사용 예시:

#pragma vertex vert
#if defined(SHADER_API_XBOXONE) || defined(SHADER_API_PS4)
#pragma fragment ConsoleFrag
#elif defined(SHADER_API_SWITCH) || defined(SHADER_API_MOBILE)
#pragma fragment MobileFrag
#else
#pragma fragment DesktopFrag
#endif

유효하지 않은 사용 예시:

#pragma multi_compile __ A B
#pragma vertex vert
#if defined(A)
#pragma fragment FragA
#elif defined(B)
#pragma fragment FragB
#else
#pragma fragment Frag
#endif

프리프로세싱 동작 변경

새로운 셰이더 프리프로세싱 솔루션은 동작 측면에서 다음과 같은 차이점이 있습니다.

  • #pragma warning 지원
  • #include 지시문 파라미터가 일반적인 형식(‘#include <my_include_file>’ 또는 ‘#include “my_include_file”’)과 일치하지 않으면 매크로로 확장됨
  • #line 지시문 파라미터는 일반적인 형식('#line' 이후에 무부호 정수 및 파일 이름(선택 사항)이 오는 경우)과 일치하지 않으면 매크로로 확장됨
  • 매크로를 재정의한 경우, 새 정의가 기존 정의와 다르면 경고 발생
  • 매크로 확장이 C 언어 표준을 전적으로 준수함
  • 첫 번째 인수가 식별자인 경우 잘못된 형식의 #undef 지시문이 더 이상 무시되지 않음
  • 문자열화(stringizing)가 완전히 지원됨
  • 매크로에서 인수 없이 문자열 연결이 작동함
  • 문자열 연결이 잘못되면 경고가 발생함
  • 문자열화 또는 문자열 연결에 사용될 때 매크로 파라미터가 확장되지 않음
  • 조건식에서 시프트(shift) 연산자가 지원됨
  • 프리프로세서가 파라미터가 있어야 하는 매크로 이름에 파라미터가 없는 경우를 발견했을 때 오류가 생성되지 않으며 매크로 확장이 발생하지 않음
  • '\\\n'(역슬래시 및 줄바꿈 기호)이 더 이상 공백으로 간주되지 않음

이제 기존의 셰이더 임포트 파이프라인이 UNITY_OLD_PREPROCESSOR 매크로를 정의하여 두 개의 프리프로세서를 구분합니다.

의견을 공유해주세요

Caching Shader Preprocessor는 새로운 기능으로, Unity 2020.1에서는 실험 기능으로 포함되며 모든 플랫폼과 렌더 파이프라인에 적용됩니다.

2020년 버전 주기의 마지막 버전에서는 정식으로 사용 가능하도록 지원할 계획이므로 Unity 2020.1 베타 버전을 사용해보시고 포럼에 피드백을 올려주세요.

2020년 5월 6일 테크놀로지 | 5 분 소요

Is this article helpful for you?

Thank you for your feedback!

다루는 주제