Unity 검색

하나의 씬에서 콘솔 개발자를 위한 10가지 그래픽스 최적화

최근 업데이트: 2019년 1월

이 페이지의 내용: 유니티의 콘솔 그래픽 개발자인 롭 톰슨(Rob Thompson, 롭 톰슨(Rob Thompson)과 )과 유니티의 데모 팀이 제공하는 콘솔 그래픽스 최적화 팁입니다. 원활한 30fps 성능을 보장할 수 있도록 매우 복잡한 씬에 최적화가 이루어졌습니다.

Unity 스크립터블 렌더 파이프라인으로 AAA 퀄리티 구현

사자의 서(이 게시물에서는 BOTD라고 부름)는 유니티의 데모 팀에 의해 제작되었습니다. BOTD는 실시간으로 렌더링된 애니메이션 단편으로, 기본적으로 새로운(그리고 여전히 실험적인) 스크립터블 렌더 파이프라인(SRP)의 기능을 시험 구동하고 보여주기 위해 만들어졌습니다. SRP를 사용하면 렌더 루프의 핵심을 C#으로 코드화할 수 있으며, 이에 따라 콘텐츠에 맞게 씬을 드로우하는 방법을 커스터마이징하는 데 있어 훨씬 더 많은 유연성을 제공합니다.

콘솔 스크립터블 렌더링 파이프라인

사용 가능한 SRP는 두 가지입니다. 고해상도 렌더 파이프라인(HDRP)은 정확도가 높은 AAA급 품질의 최신 렌더러로부터 기대하는 모든 기능을 제공하는 반면, 경량 렌더 파이프라인(LWRP)은 모바일용으로 확장 시 성능 최적화를 구현할 수 있습니다. BOTD는 HDRP를 사용하며, 이 게시물의 끝에서 SRP에 대한 고급 학습 자료를 확인할 수 있습니다.

모든 BOTD용 에셋 및 스크립트 코드는 에셋 스토어에서 에셋 스토어에서.

콘솔에서 30fps 이상의 속도로 1080p에 도달하기 위한 주요 최적화 패스

이 데모의 목적은 사람들이 전통적인 AAA 게임의 관점에서 익숙한 방식으로 게임 내에서 돌아다니고 환경을 체험할 수 있는 인터랙티브한 경험을 제공하는 데 있습니다. 특히 BOTD가 Xbox One 및 PS4에서 실행이 가능하다는 것을 보여주고 싶었습니다. 성능 요구사항은 30fps에서 1080p 그 이상이었습니다.

전체 게임이 아닌 데모인 만큼, 최적화의 주안점은 렌더링이었습니다.

일반적으로 BOTD의 성능은 수천개의 파티클이 갑자기 살아나거나 수많은 애니메이션화 된 캐릭터가 등장하는 씬이 없기 때문에 상당히 일관적입니다.

먼저 롭과 데모 팀은 가장 성능이 떨어지는 뷰, 즉 GPU 로드를 찾았습니다. 다음은 이에 대한 스크린샷입니다.

콘솔 스크립터블 렌더링 파이프라인

씬에서 일어나는 일은 상당히 일관되며, 달라지는 것은 카메라의 뷰 안에 들어오는 내용입니다. 이 씬의 부하를 줄일 수 있다면 결국 데모 전체에서 성능을 향상시킬 수 있습니다.

이 씬의 성능이 떨어진 이유는 이 레벨이 외부로부터 중심을 바라보는 뷰로 설정되어 씬에 있는 대부분의 에셋이 카메라 절두체 안에 있기 때문입니다. 이로 인해 드로우 콜이 많이 발생합니다.

요약하자면, 이 씬이 렌더링된 방법은 다음과 같습니다.

  • HDRP를 사용
  • 대부분의 아티스트 제작 텍스처 맵의 크기는 1K에서 2K 사이로 이루어지며, 일부 4K 크기의 맵도 있음
  • 간접광에는 베이크된 오클루전과 베이크된 GI를 사용하고, 태양으로부터 오는 직접광에는 단일 동적 그림자 드리우기 광원을 사용
  • 임의의 시점에서 수천회의 드로우 콜 발생(드로우 콜 및 컴퓨트 셰이더 디스패치)
  • 최적화 패스가 시작할 때 뷰는 PS4 Pro에서 약 45밀리초로 GPU 바운드
최적화 패스 이전 GPU 프레임의 모습

최적화 패스의 시작 시점에서 롭과 데모 팀은 GPU 프레임을 단계별로 살펴보고 다음과 같은 성능을 목격했습니다.

  • G-버퍼는 11ms였습니다. 유니티의 수석 그래픽스 개발자인 세바스찬 라가르데(Sebastian Lagarde)가 작성한 이 블로그 게시물에서 HDRP용 G-버퍼 레이아웃에 대한 설명을 확인할 수 있습니다.
  • 모션 벡터와 스크린 공간 앰비언트 오클루전은 각각 0.25ms와 0.6ms로 매우 빠름
  • 동적 광원을 사용하는 방향광 그림자 드리우기의 섀도우 맵은 속도가 무려 13.9ms
  • 디퍼드 라이팅은 4.9ms
  • 대기 산란은 6.6ms

이것이 GPU 프레임의 처음부터 끝까지의 모습입니다.

콘솔 GPU 프레임

보시다시피 속도는 45밀리초이며, 두 개의 수직 주황색 선은 각각 30fps와 60fps를 달성하기 위해 필요한 목표 지점을 나타냅니다.

사자의 서 제작을 위해 렌더링을 최적화한 10가지 방법

배치 개수 제어

BOTD는 데모이며 게임이 아니기 때문에 CPU 성능은 팀에게 큰 문제가 아니었습니다. 이는 전체 게임에서 필수적인 모든 시스템과 같이 진행되는 스크립트 코드의 복잡도가 없었다는 의미입니다. 다시 말하지만, 주된 관심사는 렌더링 작업을 최적화하는 것이었습니다.

그러나 배치 개수를 적게 유지하는 것은 여전히 모든 플랫폼에서 귀중한 팁입니다. 팀은 오클루전 컬링을 사용하고, 주로 GPU 인스턴싱를 사용함으로써 이를 실현했습니다. 성능 향상에 대한 확신이 있지 않은 한 콘솔에 동적 배칭을 사용하지 않도록 합니다.

이 경우에는 GPU 인스턴싱이 가장 유용한 방법입니다. 이것이 없었다면 이 씬에 대한 배치만 4,500개가 있었을 것입니다. 데모 팀은 GPU 인스턴싱을 사용함으로써 배치 수를 1,832개로 줄일 수 있었습니다.

또 하나의 중요한 점: 이 장면을 만드는 데 사용된 개별 에셋의 수는 사실 매우 적습니다. 데모 팀은 좋은 품질의 에셋을 사용하고 지능적으로 배치함으로서 반복적으로 보이지 않는 복잡한 씬을 만들었고, GPU 인스턴싱으로 낮은 배치 수를 유지했습니다.

이것은 인스턴싱이 적용되지 않은 씬입니다.

콘솔 스크립터블 렌더링 파이프라인

그리고 이것은 인스턴싱이 적용된 것입니다.

콘솔 스크립터블 렌더링 파이프라인

콘솔에서 사용 가능한 다중 코어 사용

Xbox One과 PS4는 모두 다중 코어 기기이고, 최상의 CPU 성능을 얻기 위해서는 이러한 코어를 항상 사용해야 합니다.

Unity 뉴스를 팔로우하면 Unity가 현재 고성능 멀티 스레드 시스템을 개발하고 있다는 것을 알 수 있으며, 이를 통해 현재와 미래에 사용 가능한 멀티코어 프로세서를 게임이 완전히 활용할 수 있게 될 것입니다. (매우) 간단히 말해, 이 시스템은 엔티티 컴포넌트 시스템(ECS), C# 잡 시스템, 그리고 버스트 컴파일러 세 개의 하위 시스템으로 구성됩니다.

새로운 멀티 스레드 시스템은 여전히 초기 테스트 모드에 있습니다. Unity의 그래픽스 시스템에서 그래픽스 작업 모드를 통해 사용해 볼 수 있습니다(다시 한 번 말하지만, 현재 테스트 모드로 제공). 그래픽스 작업 컨트롤은 Player Settings -> Other Settings에서 확인할 수 있습니다.

콘솔 그래픽스 잡

그래픽스 작업 모드는 소수의 배치만을 드로우하는 경우가 아니라면 콘솔의 거의 모든 상황에서 성능 최적화를 얻을 수 있습니다. 사용 가능한 두 가지 유형이 있습니다.

  • PS4에 사용 가능한 레거시 작업, 그리고 Xbox One을 위한 DirectX 11
    • 다른 코어에 작업을 배포하여 메인 스레드의 부하를 줄입니다. 매우 큰 씬에서는 Unity가 플랫폼 보유자의 그래픽스 API와 통신하기 위해 사용하는 스레드인 “렌더 스레드”에 병목 현상이 발생할 수 있다는 점에 유의하세요.
  • PS4에 사용 가능한 네이티브 작업, 그리고 Xbox One을 위한 DirectX 12(곧 출시 예정)
    • 사용 가능한 코어에 가장 많은 작업을 배포하며 규모가 큰 씬에 가장 적합한 옵션입니다.
    • 2018.2 이후부터는 최상의 옵션입니다(2018.1이나 그 이전 버전에서는 메인 스레드에 더 많은 작업을 할당하여 성능 퇴행을 초래).

플랫폼 보유 업체의 성능 분석 도구 사용

Microsoft와 Sony는 CPU와 GPU 모두에서 프로젝트의 성능을 분석하는 우수한 툴을을 제공합니다. 콘솔에서 작업 중인 경우 이들 툴을 무료로 이용할 수 있습니다. 툴에 대해 일찍 학습하여 개발 주기 동안 계속해서 사용하세요. Xbox One용 Pix는 Microsoft에서 제공하며, Razor Suite는 Sony가 제공합니다. 롭의 말대로, 이들은 이러한 플랫폼에서 최적화를 위해 활용할 수 있는 주요 툴입니다.

포스트 프로세싱 효과 프로파일링

롭은 자신이 PS4에서 Unity 게임을 프로파일링했다고 합니다. 개발자에게 알려지지는 않았지만, 포스트 프로세싱이 프레임 속도의 ⅔까지 사용했습니다. 이는 에셋 스토어에서 PC용으로 작성된 포스트 프로세싱 에셋을 다운로드하였을 때 발생하는 경우가 많습니다. 콘솔에서는 잘 실행되는 것처럼 보이지만 사실 성능 특성은 좋지 않습니다.

따라서 이러한 효과들을 적용할 때할 때 GPU에서 걸리는 시간을 프로파일링하고 화질과 성능 사이에서 만족스러운 균형을 찾을 때까지 반복합니다. 그런 다음 내버려 두세요. 모든 씬에서 정적인 비용을 구성하므로 GPU 대역폭이 얼마나 남았는지 알 수 있기 때문입니다.

반드시 필요한 경우가 아니라면 테셀레이션 사용을 피하기

일반적으로, 콘솔 게임 그래픽스에서 테셀레이션을 사용하는 것을 권장하지 않습니다. 대부분의 경우에 GPU에서 런타임 테셀레이션을 하는 것보다 동등한 수준의 아티스트 작성 에셋을 사용하는 것이 더 낫습니다.

하지만 BOTD의 경우에는, 나무껍질을 렌더링하기 위해서 테셀레이션을 사용해야만 했습니다.

콘솔 테셀레이션

테셀레이션 변위를 사용하여 노멀 매핑이 수행할 수 없는 방식으로 지오메트리의 깊이 들어간 부분과 세밀한 디테일을 더하고 정확하게 자체 그림자를 생성할 수 있었습니다.

BOTD의 대부분에서 나무는 “히어로” 오브젝트이므로 이런 수준의 작업이 진행되었습니다. LOD 0과 LOD 1의 나무들에 동일한 메시를 적용하는 방식으로 수행되었습니다. 둘 사이의 차이는 단지 테셀레이트 변위가 축소되었다는 것이며, 이 축소로 인해 LOD 1에 도달했을 때에는 더이상 효과가 없다는 점입니다.

GPU에서 항상 안정적인 웨이브 프론트 점유를 목표로 하기

어려운 용어지만, 웨이브 프론트 점유는 이해할 만한 가치가 있습니다.

웨이브 프론트는 GPU 작업의 패킷으로 생각할 수 있습니다. GPU 또는 컴퓨트 셰이더 디스패치에 드로우 콜을 제출하면, 그 작업은 여러 웨이브 프론트로 분리되고 이 웨이브 프론트들은 GPU에서 사용할 수 있는 모든 컴퓨트 단위 내의 모든 SIMD에 배포됩니다.

콘솔 웨이브 프론트 점유

각 SIMD는 동시에 사용할 수 있는 웨이브 프론트의 최대 수가 지정되어있기 때문에 GPU에서 병렬로 실행할 수 있는 웨이브 프론트의 최대 수가 지정됩니다. 얼마나 많은 웨이브 프론트를 사용하는지가 웨이브 프론트 점유로 간주되고, 이는 GPU의 잠재적인 병렬 기능을 얼마나 잘 사용할 수 있는지 이해하는데 매우 유용한 지표입니다.

Pix와 Razor가 웨이브 프론트 점유를 자세하게 보여줍니다. 위의 그래프는 Xbox One용 Pix로부터 가져온 것입니다. 왼쪽 그래프는 좋은 웨이브 프론트 점유의 예시입니다. 아래쪽의 녹색 스트립을 따라 버텍스 셰이더 웨이브 프론트가 실행되고 있고, 그 위 파란색의 경우 몇몇 픽셀 셰이더 웨이브 프론트가 실행되는 것을 볼 수 있습니다.

하지만 오른쪽에는 성능 문제가 있음을 알 수 있습니다. 많은 버텍스 셰이더 작업이 진행되지만 이것이 많은 픽셀 셰이더 작업으로 이어지지 않는 것을 보여줍니다. 이는 GPU의 잠재력을 충분히 이용하지 않는 것입니다. 그럼 이 문제의 해결을 위해 다음 최적화 팁을 살펴보겠습니다.

어떻게 이런 일이 생길까요? 이것은 픽셀을 발생시키지 않는 버텍스 셰이더 작업을 할 때 생기는 전형적인 시나리오입니다.

뎁스 프리패스 활용

Pix와 Razor에 대한 좀 더 많은 분석을 통해 G-버퍼 패스 중에 많은 오버 드로우가 발생하는 것을 볼 수 있었습니다. 이것은 특히 콘솔 상의 알파 테스트를 거친 오브젝트의 측면에서 좋지 않습니다.

콘솔에서 픽셀 버리기 명령을 내리거나 픽셀 셰이더의 뎁스에 직접 기록하면 초기 뎁스 리젝션을 활용하지 못하게 됩니다. 작업이 결국에 버려지게 되어도 픽셀 셰이더 웨이브 프론트는 여전히 실행되는 것입니다.

여기서 해결 방법은 뎁스 프리패스를 추가하는 것입니다. 뎁스 프리패스는 아주 가벼운 셰이더를 사용하여 씬의 뎁스만을 미리 렌더링하는 것입니다. 이는 더 무거운 G-버퍼 셰이더를 바인딩한 곳에서 지능적인 뎁스 리젝션을 활용할 수 있는 기반이 될 수 있습니다.

HDRP는 이제 알파 테스트된 모든 오브젝트에 대해 뎁스 프리패스를 포함하지만, 원하는 경우 전체 뎁스 프리패스를 활성화할 수도 있습니다. HDRP 제어 설정, 사용된 렌더 패스, 활성화된 기능은 모두 다음을 통해 이용할 수 있습니다.

HDRP 프로젝트에서 고해상도 렌더 파이프라인 에셋을 검색하면 HDRP에서 수행 중인 모든 작업을 제어하는 여러 체크박스를 볼 수 있습니다.

BOTD에서 뎁스 프리패스를 사용한 것은 GPU 측면에서 매우 효과적이었지만, CPU에 더 많은 배치를 드로우하는 오버헤드가 발생한다는 점을 참고하세요.

섀도우 매핑 렌더 타겟의 크기 줄이기

앞서 언급했듯이 이 씬의 섀도우 맵은 그림자를 드리우는 하나의 방향 광원에 대해 생성됩니다. 씬에는 네 개의 섀도우 맵 분할이 사용되었고 처음에는 HDRP 프로젝트의 기본값인 32비트 뎁스의 4K 섀도우 맵으로 렌더링되었습니다. 섀도우 맵에 렌더링할 때 섀도우 맵의 해상도는 대부분의 경우 제한적입니다. 이는 Pix와 Razor의 분석에 의해 뒷받침되었습니다.

섀도우 맵의 해상도를 줄이면 품질에 영향을 줄 수 있지만, 분명한 해결책입니다.

그림자 맵 해상도가 3k로 떨어져 성능 대비 충분한 균형을 이루었습니다. 데모 팀은 또한 특별히 개발자가 16비트 뎁스 그림자 맵으로 렌더링할 수 있는 옵션을 추가했습니다. 스스로 사용해 보고 싶다면 프로젝트 에셋을 다운로드하세요.

마지막으로, 섀도우 맵의 해상도를 변경했기 때문에 광원의 일부 설정을 변경해야 했습니다.

그림자 크기 축소

이때 데모 팀은 섀도우 맵에 대한 수정을 완료했고 섀도우 매핑 카메라의 위치를 변경하여 새로운 감소된 해상도를 최대한 활용하고자 노력하였습니다. 그들은 다음으로 무엇을 했을까요?

레벨 로드 시 마지막으로(가장 줌 아웃된) 섀도우 맵 분할을 한 번만 드로우합니다.

섀도우 매핑 카메라가 많이 움직이지 않기 때문에 이는 큰 문제가 되지 않았습니다. 가장 줌 아웃된 분할은 일반적으로 플레이어 카메라로부터 가장 멀리 떨어진 그림자를 렌더링하는 데 사용됩니다.

눈에 띄는 품질 저하가 발생하지 않았습니다. GPU 프레임 속도 시간과 CPU의 배치 수 감소의 두 가지 효과를 모두 얻어낸 매우 효과적인 최적화 방법이었습니다.

이 일련의 최적화 작업 후에 섀도우 맵 생성 단계는 13ms에서 8ms 미만으로 감소하였고, 조명 패스는 4.9ms에서 4.4ms로, 대기 패스는 6.6ms에서 4.2ms로 감소했습니다.

섀도우 매핑 최적화의 결과는 다음과 같습니다. 이제 PS4 Pro에서 30fps로 실행할 수 있는 범위 내에 있습니다.

콘솔 GPU 프레임

비동기 계산 활용하기

비동기 계산(Async Compute)은 유용한 컴퓨트 셰이더 작업을 통해 GPU의 활용도가 낮은 기간을 최소화하는 데 사용할 수 있는 방법입니다. 현재는 PS4에서만 지원되지만 곧 Xbox One용 DX12에서도 지원됩니다. Unity의 커맨드 버퍼 인터페이스를 통해 이용할 수 있습니다. SRP만을 위한 것은 아니지만 주로 SRP를 목표로 합니다. 코드 예시는 BOTD 에셋 또는 HDR PSOS에서 확인할 수 있습니다.

섀도우 매핑으로 수행하는 뎁스 전용 단계는 기존에 GPU의 잠재력을 최대한 활용하지 못하는 단계입니다. 비동기 계산을 사용하면 컴퓨트 셰이더 작업을 그래픽스 대기열과 병렬로 실행하여 그래픽스 대기열에서 활용되지 않는 리소스를 사용할 수 있습니다.

BOTD는 디퍼드 라이팅의 일환으로 타일링된 광원 목록을 수집하기 위해 비동기 계산을 사용하며, 대부분의 작업은 HDRP의 콘솔에서 컴퓨트 셰이더를 사용하여 수행됩니다. 비동기식 계산은 또한 SSAO 계산에서도 활용합니다. 이 두 가지 모두 섀도우 맵 렌더링과 중첩되어 웨이브 프론트 활용의 빈틈을 메꿔줍니다.

비동기 계산이 사용되는 일부 개념적 코드의 시연을 보려면 롭의 Unite 세션의 35분 30초를 참고하세요.

리소스 더 보기
확인

유니티에서는 웹 사이트의 모든 기능을 최대로 이용할 수 있도록 쿠키를 사용합니다. 자세한 정보는 쿠키 정책 페이지를 참조하세요.