Version: 2023.2
언어: 한국어
셰이더 에셋
비동기 셰이더 컴파일

셰이더 컴파일

개요

프로젝트를 빌드할 때마다 Unity 에디터는 빌드가 필요로 하는 모든 셰이더, 즉 필요한 모든 그래픽스 API에 대해 필요한 모든 셰이더 배리언트를 컴파일합니다.

Unity 에디터에서 작업할 때 에디터는 모든 요소를 미리 컴파일하지 않습니다. 모든 그래픽스 API에 대해 모든 배리언트를 컴파일하는 데에는 매우 오랜 시간이 소요될 수 있기 때문입니다.

대신 Unity 에디터는 다음을 수행합니다.

  • 셰이더 에셋을 임포트할 때는 최소한의 프로세싱(예: 표면 셰이더 생성)을 수행합니다.
  • 셰이더 배리언트를 표시해야 하는 경우, Library/ShaderCache 폴더를 확인합니다.
  • 동일한 소스 코드를 사용하는, 이전에 컴파일된 셰이더 배리언트를 찾으면 해당 배리언트를 사용합니다.
  • 일치하는 항목을 찾을 수 없으면 필요한 셰이더 배리언트를 컴파일하여 캐시에 결과를 저장합니다.
    • 참고: 비동기 셰이더 컴파일을 활성화하면 이를 배경에서 수행하고 그동안 플레이스홀더 셰이더를 표시합니다.

셰이더 컴파일은 UnityShaderCompiler라는 프로세스를 사용합니다. 다수의 UnityShaderCompiler 프로세스가 시작될 수 있어 (보통 컴퓨터의 CPU 코어당 하나) 플레이어 빌드 시에 셰이더 컴파일이 동시에 진행될 수 있습니다. 에디터는 셰이더를 컴파일하지 않고 컴파일러 프로세스는 아무 일도 하지 않으며 컴퓨터 리소스를 소비하지 않습니다.

자주 변경되는 셰이더가 많으면 셰이더 캐시 폴더가 꽤 커질 수 있습니다. 이 폴더는 Unity가 셰이더 배리언트를 다시 컴파일하게 만들 뿐이므로 삭제하는 것이 안전합니다.

플레이어 빌드 시에는 “아직 컴파일되지 않은” 모든 셰이더 배리언트가 컴파일되므로 이러한 배리언트들이 에디터가 사용하지 않았어도 게임 데이터에 포함됩니다.

서로 다른 셰이더 컴파일러

다음과 같이 플랫폼마다 서로 다른 셰이더 컴파일러를 셰이더 프로그램 컴파일에 사용합니다.

  • DirectX를 사용하는 플랫폼은 Microsoft의 FXC HLSL 컴파일러를 사용합니다.
  • OpenGL(Core 및 ES)을 사용하는 플랫폼은 Microsoft의 FXC HLSL 컴파일러를 사용하며, 이후 HLSLcc를 사용하여 GLSL로 바이트코드 변환을 수행합니다.
  • Metal을 사용하는 플랫폼은 Microsoft의 FXC HLSL 컴파일러를 사용하며, 이후 HLSLcc를 사용하여 Metal로 바이트코드 변환을 수행합니다.
  • Vulkan을 사용하는 플랫폼은 Microsoft의 FXC HLSL 컴파일러를 사용하며, 이후 HLSLcc를 사용하여 SPIR-V로 바이트코드 변환을 수행합니다.
  • 콘솔 플랫폼과 같은 여타 플랫폼은 각각 해당하는 컴파일러를 사용합니다.
  • 표면 셰이더는 코드 생성 분석 단계에 HLSL 및 MojoShader를 사용합니다.

pragma 지시문을 사용하여 여러 셰이더 컴파일러 설정을 설정할 수 있습니다.

캐시 셰이더 프리 프로세서

셰이더 컴파일에는 여러 단계가 소요됩니다. 첫 단계는 프리 프로세싱입니다. 이 단계에는 프리 프로세서라는 프로그램이 컴파일러의 셰이더 소스 코드를 준비합니다.

이전 Unity 버전에서는 셰이더 컴파일러가 현재 플랫폼에 제공하는 프리 프로세서를 에디터가 사용했습니다. 이제 Unity는 캐시 셰이더 프리 프로세서라고도 하는 자체 프리 프로세서를 사용합니다.

캐시 셰이더 프리 프로세서는 더 빠른 셰이더 임포트와 컴파일에 최적화되어 있습니다. 이 프리 프로세서는 중간 프리 프로세싱 데이터를 캐시하여 작동하므로, 에디터는 include 파일의 콘텐츠가 변경되는 경우에만 해당 파일을 파싱하면 되며 같은 셰이더의 여러 배리언트를 더 효율적으로 컴파일할 수 있습니다.

캐시 셰이더 프리 프로세서와 이전 동작의 차이를 자세히 알아보려면 Unity 포럼의 글 새로운 셰이더 프리 프로세서를 참조하십시오.

에셋 번들과 셰이더

에셋 번들을 사용하는 경우, 두 개 이상의 오브젝트에서 하나의 셰이더를 참조하는 경우 Unity에서 중복 셰이더를 컴파일할 수 있습니다.예시:

  • 에셋 번들의 머티리얼과 빌드된 씬의 머티리얼은 동일한 셰이더를 참조합니다.
  • 여러 개의 에셋 번들에는 에셋 번들 외부에서 동일한 셰이더를 참조하는 머티리얼이 포함되어 있습니다.

이렇게 하면 셰이더가 사용하는 메모리와 저장 공간이 증가하고 드로우 콜 배칭이 중단될 수 있습니다.

이를 방지하려면 다음 방법을 사용하십시오.

  • 먼저 모든 셰이더가 포함된 에셋 번들을 로드한 다음 셰이더를 참조하는 에셋 번들 에셋을 로드하고 인스턴스화합니다.자세한 내용은 에셋 번들 종속성을 참조하십시오.
  • 에셋 번들을 구조화하여 중복을 최소화하십시오.자세한 내용은 에셋 중복을 참조하십시오.

머티리얼과 셰이더 배리언트 컬렉션을 에셋 번들에 추가하여 포함할 셰이더 배리언트를 지정할 수 있습니다.

하나의 에셋 번들을 생성하면 에셋 번들을 부분적으로 언로드할 수 없기 때문에 일부 셰이더는 더 이상 필요하지 않더라도 메모리에 남아있을 수 있습니다.함께 사용하는 셰이더 그룹마다 별도의 에셋 번들(예: ‘숲’ 에셋 번들 및 ‘사막’ 에셋 번들)을 생성하면 이러한 문제를 방지할 수 있습니다.어드레서블을 사용한다면 로드된 에셋 번들 또는 어드레서블 시스템의 메모리 관리를 참조하십시오.

에셋 번들 브라우저를 사용하여 에셋 번들 내 어떤 에셋이 다른 에셋에 종속되어 있는지 확인하고 중복된 에셋이 있는지 확인할 수 있습니다.

빌드 타임 스트리핑

Unity는 게임 빌드 중에 게임에서 사용되지 않는 몇몇 내부 셰이더 배리언트를 찾아 빌드 데이터에서 제외(“strip”)할 수 있습니다. 자세한 내용은 셰이더 배리언트를 참조하십시오.

셰이더 에셋
비동기 셰이더 컴파일