Unity DrawCall Batching
Batch
- DrawCall = Set VB/IB + Set Transform + SetPass Call
- SetPass Call = Set Shader + Set Texture(0~7) + Set Blending + Set Z enable + …
동적배칭
동적 배칭(메시)
Unity는 같은 머티리얼을 공유하고 다른 조건을 충족하는 움직이는 게임 오브젝트를 동일 드로우 콜 안에 자동으로 배칭할 수 있습니다. 동적 배칭은 추가적인 작업 없이 자동으로 수행됩니다.
- 동적 게임 오브젝트 배칭은 리소스 사용량이 버텍스마다 일정하므로, 900개 미만의 버텍스 속성과 300개 미만의 버텍스가 포함된 메시에만 적용됩니다. 쉐이더가 버텍스 포지션, 노멀 및 싱글 UV를 사용하는 경우 버텍스를 300개까지 배칭할 수 있는 한편, 셰이더가 버텍스 포지션, 노멀, UV0, UV1 및 탄젠트를 사용하는 경우 180까지만 배칭할 수 있습니다. 참고: 속성 카운트 제한은 향후 변경될 수 있습니다.
- 트랜스폼에 미러링이 포함된 게임 오브젝트는 배칭되지 않습니다. 예를 들어 스케일이 +1인 게임 오브젝트 A와 스케일이 –1인 게임 오브젝트 B를 함께 배칭할 수 없습니다.
- 다른 머티리얼을 사용하면 본질적으로 같은 게임 오브젝트도 함께 배칭되지 않습니다. 단, 섀도우 캐스터 렌더링은 예외입니다.
- 라이트맵이 있는 게임 오브젝트에는 라이트맵 인덱스와 라이트맵으로 오프셋/스케일이라는 추가 렌더러 파라미터가 있습니다. 일반적으로 동적 라이트맵이 적용된 게임 오브젝트는 배칭할 라이트맵 위치와 정확히 똑같은 위치를 가리켜야 합니다.
- 멀티 패스 Shaders는 배칭을 중단합니다. 거의 모든 Unity 셰이더는 포워드 렌더링 시에 몇 가지 광원을 지원하여 사실상 추가 패스를 대신 수행합니다. “픽셀당 추가 라이트”에 대한 드로우 콜은 배칭되지 않습니다. Legacy Deferred(광원 프리패스) 렌더링 경로는 게임 오브젝트를 두 번 드로우해야 하기 때문에 동적 배칭이 불가능합니다.
동적 배칭은 모든 게임 오브젝트 버텍스를 CPU에서 월드 공간으로 변환하는 방법으로 작동하므로, 이 작업이 드로우 콜을 수행하는 것보다 더 작은 경우에만 더 유리합니다. 드로우 콜의 리소스 요구사항은 주로 사용되는 그래픽스 API를 비롯한 여러 요인에 따라 달라집니다. 예를 들어 콘솔이나 Apple Metal 같은 최신 API에서는 드로우 콜에 사용되는 리소스가 일반적으로 훨씬 더 적고, 종종 동적 배칭이 전혀 유리하지 않을 수 있습니다.
동적 배칭(파티클 시스템, 라인 렌더러, 트레일 렌더러)
Unity가 동적으로 생성하는 지오메트리가 포함된 컴포넌트의 경우 동적 배칭은 메시에 대한 동적 배칭과 다르게 동작합니다.
- 호환 가능한 렌더러 타입 각각에 대해 Unity는 모든 배칭 가능한 콘텐츠를 하나의 커다란 버텍스 버퍼로 빌드합니다.
- 렌더러는 배치에 대한 머티리얼 상태를 설정합니다.
- Unity는 버텍스 버퍼를 그래픽스 기기에 바인드합니다.
- 배치의 렌더러 각각에 대해 Unity는 오프셋을 버텍스 버퍼로 업데이트한 다음 새로운 드로우 콜을 제출합니다.
그래픽스 기기 호출의 성능 부하를 측정하는 경우 컴포넌트 렌더링의 가장 느린 부분이 머티리얼 상태로 설정됩니다. 다양한 오프셋의 드로우 콜을 공유 버텍스 버퍼로 제출하면 비교적 속도가 매우 빠릅니다.
이러한 방식은 정적 배칭을 사용할 때 Unity가 드로우 콜을 제출하는 방법과 매우 유사합니다.
정적(Static) 배칭
정적 배칭을 사용하면 엔진이 움직이지 않고 동일 머티리얼을 공유하는 모든 크기의 지오메트리에 대해 드로우 콜을 줄일 수 있습니다. (CPU에서 버텍스를 변환하지 않으므로)종종 동적 배칭보다 더 효율적이지만, 메모리를 더 많이 사용합니다.
정적 배칭을 이용하여 이득을 얻기 위해서는 특정 게임 오브젝트가 정적이고 게임에서 움직이거나 회전하거나 스케일하지 않음을 명시적으로 지정해야 합니다. 이렇게 하려면 인스펙터에서 Static 체크박스를 사용하여 게임 오브젝트가 정적임을 표시해야 합니다.
정적 배칭을 사용하면 결합된 지오메트리를 저장할 메모리가 더 필요합니다. 정적 배칭 전에 몇몇 게임 오브젝트가 동일한 지오메트리를 공유한 경우, 각 게임 오브젝트에 대해 지오메트리의 복사본이 에디터에서, 또는 런타임 시점에 생성됩니다. 이렇게 하는 것이 항상 바람직하지는 않을 수 있습니다. 때로는 일부 게임 오브젝트의 메모리 사용량을 적게 유지하기 위해 정적 배칭을 방지하여 렌더링 성능 저하를 감수해야 합니다. 예를 들어 밀집한 숲 레벨에서 나무를 정적으로 표시하면 메모리에 중대한 영향을 미칠 수 있습니다.
내부적으로 정적 배칭은 정적 게임 오브젝트를 월드 공간으로 변환하고 하나의 공통 버텍스 및 인덱스 버퍼를 빌드하여 작동합니다. Player 설정에서 Optimized Mesh Data 를 활성화하면 Unity는 버텍스 버퍼를 빌드할 때 셰이더 배리언트에서 사용하지 않는 모든 버텍스 요소를 제거합니다. 이 작업을 수행하기 위해 특별한 키워드 검사를 수행할 수도 있습니다. 예를 들어, Unity가 LIGHTMAP_ON 키워드를 감지하지 못하면 배치에서 라이트맵 UV를 제거합니다. 그런 다음 동일한 배치에 표시되는 게임 오브젝트의 경우 Unity는 일련의 간단한 드로우 콜을 수행합니다. 이때 각 드로우 콜 간에는 상태 변화가 거의 없습니다. 기술적으로 Unity는 API 드로우 콜을 저장하는 대신 드로우 콜 간의 상태 변화를 저장(리소스 소모가 심함)합니다. 배치 한도는 대부분의 플랫폼에서 64,000개 버텍스와 64,000개 인덱스입니다(OpenGLES는 48,000개 인덱스, macOS는 32,000개 인덱스).
출처 : Unity Document
드로우콜 줄이기
- Texture Atlas
- 하나의 material 공유
- Realtime shadow ShadowMap 생성에 따라 오브젝트를 2번 그려 2배 늘어남
- LightMap & Light Probe 사용
- QualitySetting에 Pixel Light Count를 0으로 설정(이 설정을 사용하면 Vertex Lighting이 됨)
- Light의 Render Mode를 Not Important로 설정(이 설정을 사용하면 Vertex Lighting이 됨)
- Light를 사용하지 않는 MatCap Shader 사용
- Occlusion Culling 사용
- LOD Group사용
참조 : Unite Seoul 2016 그래픽 최적화로..