Dev/Unity
[Unity] 병목 - 유니티 그래픽스 최적화 스타트업 정리
_cpdm_
2025. 2. 10. 13:47
반응형
병목
최적화를 수행하기 위해 다양한 방법들이 있겠으나, 선행되어야 할 것이 병목을 탐지하는 것
- 일반적으로 수행되는 최적화 목록
- Mesh의 Vertex 줄이기
- Texture 사이즈 줄이기
- Shader를 가볍게
- Draw Call 줄이기
- Logic 최적화
- 물리 연산 줄이기
Bottle neck, 병목
- 전체 프로세스가 갑자기 느려지거나 막혀서 정지하는 부분
- 그래서 어떤 부분에서 병목현상이 일어나는지를 알기위해 프로파일링이 중요하다.
Profiling
- 병목 지점을 찾는 과정
- 원인을 찾아서 최적화를 수행한다.
FPS와 Frame Time
- Frame Time
- 한 Frame을 처리하는 데 걸리는 시간 -> 프로파일링 할 때 Frame Time으로 하는 것이 좋다.
- 일반적으로 Frame Time은 ms 단위로 측정
- Editor의 Game 뷰 좌상단의 Stats를 누르면 FPS와 Frame Time 확인 가능
- Editor에서의 성능 측정은 큰 의미가 없기 때문에 실제 디바아ㅣ스에서 측정해야 함.
- Time.unscaledDeltaTime
- 한 Frame 처리를 위한 시간
구간 측정
- 성능을 측정할 때 중요한 포인트?
- 각 Frame을 렌더링하는데 시간이 얼마나 걸리는지
- FPS로만 측정하기 보다는 어디에서 얼마나 시간이 걸렸는지를 알기 위해 Frame Time으로 측정하는 것이 좋다.
선형 측정
- FPS 값은 비선형적인 변화를 보이기 때문에 성능 저하가 일정하게 일어나고 있는지 판단하기 어려움
- 예시
- 오브젝트 하나를 추가할 때마다 FPS가 떨어지는 것을 측정했는데 변화가 90 -> 45 -> 30 이라고 가정
- 일정하게 변화한 것으로 보이는 가?
- 1 Object = 90 FPS = 1000/90.0 = 11.1ms
- 2 Objects = 45 FPS = 1000/45.0 = 22.2ms
- 3 Objects = 30 FPS = 1000/30.0 = 33.3ms
- 실제로는 일정하게 변화한 것이 맞다.
- 따라서 Frame Time으로 측정해야 변화량을 제대로 측정할 수 있다는 결론
- 오브젝트 하나를 추가할 때마다 FPS가 떨어지는 것을 측정했는데 변화가 90 -> 45 -> 30 이라고 가정
측정 시나리오
- 측정은 여러번 측정 후 평균 값을 계산
- 여러 Scene, 여러 상황에서 다양하게 측정하는 것이 좋음
- Deferred Randering Path는 기본적으로 대역폭 요구 성능이 크다.
- 후처리 효과들도 기본 비용이 크다.(Bloom 등.)
Target Frame Rate
- 모바일 디바이스가 쓰로틀링에 걸리지 않게 강제로 최대 FPS를 설정할 수 있음
- Application 시작 시 Application.targetFrameRate = 40; 을 설정하면 40FPS로 설정.
VSync ( 수직 동기화 )
- 모니터 주파수와 렌더링 퍼포먼스를 맞춰 Tearing 현상(물결치는현상)을 방지하는 역할
- Tearing
- 모니터는 화면 갱신 주파수에 한계가 있음
- 이를 넘는 신호를 입력하면 화면이 물결치거나 찢어지는 듯한 현상 -> Tearing
- Back Buffer가 아직 렌더링 되고 있는 동안 Front Buffer와의 전환이 이루어져 현 화면과 이전 화면이 섞여서 나타나는 현상
- 이를 방지하기 위한 것이 VSync로, 모니터의 주파수에 맞게 렌더링 퍼포먼스를 조절해준다
- Tearing
- targetFrameRate를 높게 설정했음에도 60FPS를 넘지 못한다면 VSync를 의심
- 성능 측정 시에는 꺼주는 것이 좋음
- Edit > Project Settings > Quality > Don't Sync
- Edit > Project Settings > Quality > Don't Sync
Throttling을 고려한 측정
- 성능 프로파일링 시 Throttling을 고려해야 한다.
- 고려 사항
- 디바이스가 얼마나 빠르게 Throttling 상태로 진입하고, 얼마나 성능이 떨어지는 지
- 발열 관리
- 배터리는 항상 100%
- 측정 후 다음 측정까지 5분 대기
- 쿨링
CPU Bound vs GPU Bound
- 병목이 CPU에서 발생하는 지 GPU에서 발생하는 지 확인이 필요
- CPU와 GPU는 병렬처리 방식이다.
- CPU는 명령을 주고 계속 자기 일을 처리한다.
- 한 Frame에서 CPU는 일처리를 모두 마쳤지만, GPU는 받은 작업들을 순차 처리 중인데 아직 끝나지 않았다면 CPU는 기다리게 된다.
- 이를 GPU 바운드 상태라고 하고 GPU의 작업을 줄ㄹ여야 한닫.
- 반대로 GPU가 대기하고 CPU가 연산 중인 상황을 CPU 바운드라고 하며 CPU 작업을 줄여줘야 한다.
병목 측정 및 탐지
Unity Profilier
- 유니티에서 제공하는 프로파일러
- Window > Analysis > Profiler
- 프로파일러 연결은 개발 빌드로 연결해야하며 측정 부하가 포함된다. ( = 릴리즈 빌드와 차이가 있음 )
- 에디터 측정은 의미 없다.
- 단, GPU 병목은 내장 프로파일러로는 디테일하게 파악이 힘들다.
- Android는 Graphics API가 Vulkan일 경우 지원 가능.
- Snapdragon 칩셋을 사용하는 디바이스는 Qualcomm에서 제공하는 전용툴로 GPU 프로파일링 툴인 Snapdragon Profiler 사용
- IOS는 XCode에서 제공하는 GPU FrameDebugger 이용
Fillrate
- 그래픽카드가 1초에 스크린에 렌더링할 수 있는 픽셀의 수
- 게임 렌더링에서는 픽셀 처리에 대한 부담을 모두 포함한 개념
- 필레이트 = 화면 픽셀 수 x 프래그먼트 쉐이더 복잡도 x 오버드로우
- 픽셀이 많거나 프래그먼트 쉐이더가 너무 복잡하면 Rasterizer 단계에서 병목이 발생
-> 이때 필레이트가 병목이 되었다고 표현 (필레이트 바운드) - 디스플레이 해상도를 변경했을 때 성능이 눈에 띄게 좋아진다면 해상도(렌더링 해야하는 픽셀 수)가 원인으로 필레이트 병목을 강하게 의심할 수 있다.
- 해상도 설정
- Edit > Project Settings > Player > Resolution Scaling 항목 수정
- Mode는 기본적으로 Disabled, Fixed DPI로 변경하여 DPI에 맞게 자동 조정 가능
(DPI가 낮을 수록 해상도가 낮게 조절) - Screen.SetResolution() 활용
- 해상도 설정
오버드로우
- 화면에 렌더링 되는 픽셀이 여러 번 덧그려지는 현상
(채워진 픽셀을 또 다른 Object를 렌더링하면서 다시 그리면 오버드로우라고 함) - ZBuffer가 오버드로우 방지를 도와준다.
- Camera와의 거리 순으로 정렬하여 앞부터 그리므로 뒤에 가려지는 부분은 안그린다.
- 투명 / 불투명 오브젝트
- 불투명 오브젝트는 카메라 앞에서 뒤로 정렬.
- 뒤에 있는 오브젝트의 가려지는 픽셀은 렌더링을 건너 뛴다.
- 투명 오브젝트는 카메라 뒤에서 앞으로 정렬
- 모든 픽셀에서 오버드로우가 발생.
- 불투명 오브젝트는 카메라 앞에서 뒤로 정렬.
- 파티클
- 파티클의 밀도가 높을 수록 오버드로우가 많아진다.
포스트 프로세싱
- Fragment 쉐이더가 무거워지는 요인 중 하나이다.
- 포스트 프로세싱이 병목의 원인이라면 해상도를 줄이면 해결된다.
- 포스트 프로세싱 종류별로 성능 비용이 다르다.
- Color Grading은 모바일에서도 부담이 없다.
- Bloom까지도 최근 디바이스의 성능이 좋아지면서 사용된다.
- DOF는 모바일에 적용하기에는 성능 부담이 크기 때문에 컷씬이나 로비등에서 사용한다.
Upscaling Sampling
- 해상도를 줄이면 성능을 올릴 순 있지만, 유저가 알아보기 쉽다.
- UI의 해상도를 유지하고 3D 씬만 낮은 해상도로하여 트릭을 주는 것이 업스케일링.
- 구현 순서
- 저해상도 Render Texture 생성
- 3D 씬을 Render Texture에 렌더링
- Render Texture를 업스케일링 해서 현재 Back Buffer에 렌더링
- Overlay UI 렌더링
- 핵심은 전체 해상도를 줄이는 것이 아니라는 것
Polygon
- 폴리곤 수가 많다 = 버텍스 수가 많다 -> Geometry 부분에서 병목이 생긴다.
- Vertex Shader를 많이 수행한다.
- 폴리곤 수를 줄였을 때 성능을 체크해본다.
- LOD ( Level of Detail)
- 디테일에 단계를 나누는 것
- 가까이 있는 건 자세히 그리고, 카메라에서 멀리 있는 건 디테일을 떨어뜨린다.
- 이를 바탕으로 vertex 수를 줄인다.
- Edit > Project Settings > Quality > Other 에서 LOD Bias를 조절할 수 있다.
Texutre
- 전체 텍스쳐의 해상도를 조절해보면서 병목 원인인지 아닌지 확인할 수 있다.
- 텍스쳐 해상도 조절
- Edit > Project Settings > Quality > Rendering 섹션
cpdm
choppadontbiteme.tistory.com
반응형