비동기 셰이더 컴파일은 새로운 셰이더 배리언트를 컴파일하는 동안 더미 셰이더를 렌더링하여 Unity 에디터가 지연되지 않도록 만듭니다. 비동기 셰이더 컴파일은 기본적으로 에디터 설정(메뉴: Edit > Project Settings… > Editor > Shader Compilation)에서 활성화되어 있습니다.
셰이더는 수백 개 또는 수천 개의 배리언트로 구성되어 있으며 여러 개의 키워드 조합이 포함된 다양한 사용 시나리오를 처리합니다. 에디터가 셰이더를 로드할 때 모든 배리언트를 컴파일해야 한다면 셰이더 임포트 프로세스가 매우 느릴 수 있습니다. 이런 문제를 해결하기 위해 Unity는 기본적으로 온디맨드 셰이더 컴파일 을 사용합니다. 즉, 에디터가 씬에서 셰이더 배리언트와 처음 만날 때 셰이더 배리언트를 컴파일합니다. 이 경우 전체 셰이더 컴파일에 걸리는 시간이 몇 밀리초에서 몇 초에 이르기까지 다양하기 때문에 에디터의 렌더링이 지연될 수 있습니다. 셰이더 배리언트를 컴파일하는 데 걸리는 시간은 선택한 그래픽스 API와 셰이더의 복잡도에 따라 다릅니다. 이러한 지연을 해결하려면 비동기 셰이더 컴파일 을 사용하십시오.
비동기 셰이더 컴파일은 기본적으로 활성화되지만, 게임(Game) 뷰 또는 씬(Scene) 뷰에 대해 비활성화할 수 있습니다. 이는 렌더링 솔루션의 어느 부분이 문제를 일으키는지 알 수 없을 때 유용합니다. 하지만 셰이더 컴파일 동안 에디터에서 여전히 지연이 발생할 수 있습니다.
비동기 셰이더 컴파일을 비활성화하려면 다음을 수행하십시오.
1) 프로젝트에서 Edit > Project Settings.. > Editor 로 이동합니다.
2) 에디터 설정 하단의 Shader Compilation 에서 Asynchronous Shader Compilation 체크박스를 선택 해제합니다.
참고: 비동기 셰이더 컴파일을 비활성화하면 씬 뷰와 게임 뷰에만 영향을 미칩니다. 비동기 셰이더 컴파일을 명시적으로 활성화하는 커스텀 스크립트와 시스템에는 아무런 영향도 없습니다.
비동기 셰이더 컴파일을 사용하면 에디터가 컴파일 대기열에 셰이더 배리언트를 추가하고 작업 스레드에서 완료합니다. 즉시 컴파일하지는 않습니다. 렌더링 지연을 피하기 위해 에디터는 셰이더 배리언트를 컴파일하는 동안에도 계속 렌더링을 수행합니다. 그런 다음 에디터는 일반 청록색 더미 셰이더로 셰이더 배리언트의 스폿을 채웁니다(때때로 깜박거리는 청록색 더미 셰이더를 통해 배경에서 진행 중인 작업을 알 수 있음). 이렇게 하면 에디터가 계속 컴파일하기 때문에 일부 오브젝트가 씬에서 렌더링되지 않는 문제를 방지할 수 있습니다. 컴파일이 끝나면 에디터가 실제 셰이더를 교체해 넣습니다. 에디터의 오른쪽 하단 코너에 있는 진행 표시줄은 컴파일 대기열의 상태를 보여줍니다.
빌드 프로세스 동안 에디터가 플레이어에 필요한 모든 셰이더 배리언트를 컴파일하므로 이 기능은 스탠드얼론 플레이어에 아무 영향도 주지 않습니다.
참고: 기본적으로 비동기 셰이더 컴파일은 씬 뷰와 게임 뷰에서 작동합니다. 다른 시나리오에서 사용하고 싶은 경우 커스텀 에디터 툴에서 비동기 셰이더 컴파일 사용을 참조하십시오.
참고: DrawProcedural
또는 CommandBuffer.DrawProcedural
을 사용하는 경우 에디터는 더미 셰이더를 교체해 넣는 대신, 셰이더 배리언트 컴파일을 완료할 때까지 이 셰이더 배리언트에 대한 렌더링을 건너뜁니다.
참고: blit 동작은 비동기 셰이더 컴파일을 사용하지 않습니다. 이는 가장 일반적인 사용 사례에서 올바른 출력을 보장하기 위함입니다.
기본적으로 비동기 셰이더 컴파일은 씬 뷰와 게임 뷰에서 작동합니다. 고급 렌더링 솔루션은 데이터를 한 번 생성하면 이후 프레임에서 해당 데이터를 재사용하며, 이로 인해 더미 셰이더가 생성된 데이터를 오염시킬 수 있습니다. 이런 일이 발생하면 셰이더가 컴파일을 완료한 후에도 씬에서 청록색 컬러나 다른 렌더링 결함이 표시될 수 있습니다. 이 문제는 에디터가 데이터 생성 셰이더 배리언트와 처음 만날 때에만 발생합니다. 하지만 이러한 문제를 피하기 위해 렌더링의 일부분에 대해 비동기 셰이더 컴파일을 비활성화하거나, 일부 셰이더에 대해 비동기 셰이더 컴파일을 강제로 적용하거나, 특정 데이터 오염을 감지하고 컴파일 완료 시 데이터를 다시 생성할 수 있습니다.
비동기 셰이더 컴파일을 사용하고 싶지만 더미 셰이더가 특정 렌더링 호출에 대한 렌더링 결과에 영향을 미치는 것을 원치 않는 경우 C# 스크립트에 해당 호출에 대한 기능을 비활성화할 수 있습니다. 다음 명령어는 즉각적인 범위와 CommandBuffer 범위에서 기능을 비활성화하는 방법을 보여줍니다. 두 경우 모두에서 Unity가 비동기적으로 컴파일하길 원하지 않는 렌더 호출 주위에 클램프를 삽입해야 합니다.
_즉각적인 범위_에서는 ShaderUtil.allowAsyncCompilation;
을 사용해야 합니다.
ShaderUtil.allowAsyncCompilation
의 현재 상태를 변수에 저장하십시오.
비동기 컴파일을 비활성화할 렌더 커맨드를 호출하기 직전에 ShaderUtil.allowAsyncCompilation
을 false
로 설정하십시오.
그런 다음 영향을 주고 싶은 렌더링 호출 이후에 ShaderUtil.allowAsyncCompilation
을 1단계에서 저장한 이전 상태로 다시 복원해야 합니다.
다음은 유사 코드 예제입니다.
// Store the current state and disable async compilation
bool oldState = ShaderUtil.allowAsyncCompilation;
ShaderUtil.allowAsyncCompilation = false;
// Enter your rendering code that should never use the dummy shader
Graphics.DrawMesh(...);
// Restore the old state
ShaderUtil.allowAsyncCompilation = oldState;
CommandBuffer 범위에서는 ShaderUtil.SetAsyncCompilation
과 ShaderUtil.RestoreAsyncCompilation
을 사용해야 합니다.
비동기 컴파일을 비활성화할 렌더 커맨드를 호출하기 직전에 ShaderUtil.SetAsyncCompilation
을 호출한 후 false
로 설정하십시오. 그러면 버퍼에서 바로 이후에 따라오는 커맨드가 비동기 컴파일을 허용하지 않습니다.
영향을 주고 싶은 렌더링 커맨드 이후에 Shader.Util.RestoreAsyncCompilation
을 사용하십시오.
다음은 유사 코드 예제입니다.
// Disable async compilation for commands followed by this
ShaderUtil.SetAsyncCompilation(cmd, false);
/// Enter your rendering commands that should never use the dummy shader
cmd.DrawMesh(...);
// Restore the old state
ShaderUtil.RestoreAsyncCompilation(cmd);
특정 셰이더에 동기 컴파일을 강제로 적용할 수 있습니다. 이는 렌더링 시작 시 항상 존재해야 하는 데이터 생성 셰이더에 대해 좋은 옵션이며, 컴파일 속도가 상대적으로 빠릅니다.
특정 셰이더에 동기 컴파일을 강제로 적용하려는 경우:
셰이더 코드에서
#pragma editor_sync_compilation
지시문을 추가하십시오.
참고: 렌더링 도중에 새로운 배리언트와 만나는 복잡한 셰이더에는 동기 컴파일을 강제로 적용하지 마십시오. 복잡한 셰이더에 동기 컴파일을 강제로 적용하면 에디터에서 렌더링 지연이 발생할 수 있습니다.
더미 셰이더가 생성된 데이터를 오염시키면 오염된 데이터를 폐기하고 올바르게 컴파일된 셰이더를 사용하여 새로운 세트를 다시 생성해야 합니다.
Unity가 데이터 생성에 사용하는 머티리얼을 이미 알고 있는 경우:
ShaderUtil.IsPassCompiled
를 사용하여 머티리얼의 현재 상태에 의해 지정된 셰이더 배리언트의 컴파일 상태를 확인하십시오.
해당 상태가 Uncompiled 에서 Compiled 로 바뀐 경우 생성된 데이터를 새로 고치십시오.
오염된 데이터를 생성하는 특정 머티리얼을 모르는 경우 또는 데이터 생성이 단일 머티리얼로 한정되지 않는 경우 다음을 수행하십시오.
ShaderUtil.anythingCompiling
을 사용하여 Unity가 셰이더를 비동기적으로 컴파일하는지 확인하십시오.
비동기 컴파일이 완료되면 데이터를 새로 고치십시오.
기본적으로 비동기 셰이더 컴파일은 게임 뷰와 씬 뷰에서 작동합니다. 커스텀 에디터 툴에서 사용하려는 경우 C#을 통해 커스텀 툴에 대해 활성화할 수 있습니다.
_즉각적인 범위_에서는 ShaderUtil.allowAsyncCompilation;
을 사용해야 합니다.
ShaderUtil.allowAsyncCompilation
의 현재 상태를 변수에 저장하십시오.
비동기 컴파일을 활성화할 렌더 커맨드를 호출하기 직전에 ShaderUtil.allowAsyncCompilation
을 true
로 설정하십시오.
그런 다음 영향을 주고 싶은 렌더링 호출 이후에 ShaderUtil.allowAsyncCompilation
을 1단계에서 저장한 이전 상태로 다시 복원해야 합니다.
다음은 유사 코드 예제입니다.
// Store the current state and enable async compilation
bool oldState = ShaderUtil.allowAsyncCompilation;
ShaderUtil.allowAsyncCompilation = true;
// Enter your rendering code that you wish to utilize async compilation
Graphics.DrawMesh(...);
// Restore the old state
ShaderUtil.allowAsyncCompilation = oldState;
CommandBuffer 기반 범위에서는 ShaderUtil.SetAsyncCompilation
과 ShaderUtil.RestoreAsyncCompilation
을 사용해야 합니다.
비동기 컴파일을 활성화할 렌더 커맨드를 호출하기 직전에 ShaderUtil.SetAsyncCompilation
을 호출한 후 true
로 설정하십시오. 그러면 버퍼에서 바로 이후에 따라오는 커맨드가 비동기 컴파일을 허용합니다.
영향을 주고 싶은 렌더링 커맨드 이후에 Shader.Util.RestoreAsyncCompilation
을 사용하십시오.
다음은 유사 코드 예제입니다.
// Enable async compilation for commands followed by this
ShaderUtil.SetAsyncCompilation(cmd, true);
/// Enter your rendering commands that you wish to utilize async compilation
cmd.DrawMesh(...);
// Restore the old state
ShaderUtil.RestoreAsyncCompilation(cmd);
Graphics.ExecuteCommandBuffer(cmd);
커스텀 툴이 각 머티리얼에 대해 더미 셰이더 대신 다른 것을 그리도록 만들 수 있습니다. 이렇게 하면 청록색 셰이더 배리언트로 렌더링하지 않고, 셰이더가 컴파일하는 동안 다른 것을 그릴 수 있습니다.
특정 셰이더 배리언트가 컴파일되었는지 확인하려면 ShaderUtil.IsPassCompiled
을 사용하십시오.
컴파일을 수동으로 트리거하려면 ShaderUtil.CompilePass
를 사용하십시오. 이렇게 하면 청록색 셰이더 배리언트로 렌더링하지 않고, 셰이더가 컴파일하는 동안 다른 것을 그릴 수 있습니다.