article thumbnail image
Published 2024. 2. 22. 01:05

App에서 화면 스크롤, Pop Up 등 여러 Animation이 존재한다. 

이러한 Animation은 유저의 터치와 같은 이벤트에 의해서 발생하는데, 

App은 이러한 유저의 이벤트를 통해 변경된 UI를 화면에 Display 하는 과정Render Loop이라 부른다. 

 

Hitch

Render Loop의 각 Cycle에서 만들어지는 화면을 "Frame"이라 부른다. 

 

Swift에서 일어나는 Animation의 경우,

만화처럼 Frame을 빠르게 교체해 실제로 연속적으로 일어난것 처럼 보이게 하는 것이다.

 

만약 Frame이 제때 만들어지지 않는다면 제시간에 교체하지 못하게 되어 사용자에게 버벅거리게 보일 것이다. 

이처럼 다음 Frame이 늦어져, 애니메이션이 끊기는 시간을 "Hitch"라고 부른다.

 

이때, "refresh rate(주사율)"는 1초에 몇개의 Frame을 표시할 수 있는지를 나타내며, Hz단위로 표시한다. 

iPhone의 경우 프로 라인업은 120Hz, 일반 라인업은 60Hz의 주사율을 가지고 있다. 

60Hz 기준으로 생각해 보면, 16.67ms마다 새로운 Frame이 준비되어야 한다.

만약 시간내에 새로운 Frame이 준비되지 않는다면, 이전 Frame으로 대체하게 되며, 

이는 사용자 입장에서 화면이 버벅거리게 느끼게 된다. 

 

즉, Hitch는 Render Loop가 제시간에 Frame을 완성하지 못했기 때문에 발생한다.

 

 

Render Loop

앞서 말했지만, "Render Loop"는 다음과 같은 Process가 연속적으로 발생한다. 

  • 터치와 같은 이벤트가 App에 전달된다. 
  • 이벤트에 따른 UI 변화가 OS에 전달된다. 
  • 최종적으로 Frame을 생성해 App에 전달한다.

하나의 Process는 refresh rate시점마다 발생하는데,

앞서 말했듯 60Hz의 경우 16.67ms마다 frame이 교체된다.

120Hz의 경우 8.33ms마다 frame이 교체된다.

시스템은 교체되는 시점을 알리기 위해 "VSYNC"라는 이벤트를 발생한다.

즉, 16.67ms 혹은 8.33ms마다 VSYNC이벤트가 발생한다.

 

3 Stage Of Render Loop

Render Loop은 크게 3개의 Stage로 나눌 수 있다.

App Stage 

해당 단계에선, 이벤트가 처리되고 UI에 변경하는 단계이다. 

 

Render Server Stage

실제로 UI가 GPU에서 랜더링되는 단계이다. 

 

On the Display Stage

완성된 Frame이 화면에 표시되는 단계이다. 

 

Double Buffering & Tripple Buffering

이렇게 각 Stage는 순차적으로 진행이 되기 때문에,

VSYNC안에 작업을 마치지 못하게 되면, 다음 Stage 역시 밀리게 된다. 

이는 최종적으로 Frame이 제 시간에 준비되지 못하는 Hitch로 이어지게 된다.

 

제시간에 Frame을 준비하기 위해 Render Loop는 적어도 2 Frame 전에 시작될 필요가 있다.

 

이렇게 2Frame전에 Render Loop를 시작하는 것을 "Double Buffering"이라 부른다. 

 

또한, Hitch가 발생할 것을 대비해 3 Frame전에 Render Loop를 시작하는 것을 "Tripple Buffering"이라 부른다. 

여기선 Render Server에 2 Frame을 할당하며,  Fall Back모드이다.

 

5 Phase of Render Loop

Render Loop는 어떤 일을 하냐에 따라 5 Phase로 구분할 수 있다. 

  • Event Phase : App에서 이벤트를 처리하고, UI를 변경할지 결정하는 단계
  • Commit Phase : UI를 변경하고, 이를 Render Server에 Rendering을 요청하는 단계
  • Render Prepare Phase : GPU에서 랜더링할 수 있도록 사전준비하는 단계
  • Render Execute Phase : GPU에서 실제 랜더링하는 단계
  • Display Phase : 랜더링된 결과물을 화면에 보여주는 단계

 

Event Phase

 

"Event Phase"는 App이 Event를 처리하고 UI를 변경할지 결정하는 단계이다.

Event에는 키보드 타이핑, 네트워크 callback, 터치 등등이 있다.

 

이런 Event들로 backgroundColor, size, position 등 UI를 변경한다.  

 

이렇게 Layout이나 Display변경이 필요한 View들을 표시해 Commit Phase로 넘긴다.

 

layer의 bounds가 변경된 경우라면,

Core Animaiton 자체적으로 setNeedsLayout을 호출해 재계산 이 필요하다고 표시한다.

view의 bounds가 아닌, view.layer.bounds의 변경을 말한다.

 

Commit Phase

"Commit Phase"는 Layout을 하고 Draw를 하는 단계이다.

우선, Layout이 필요한 View들을 부모부터 배치하여 Layer Tree를 만든다. 

 

그다음, drawRect을 override한 커스텀 View나 setNeedsDisplay가 호출된 View들이 그려진다.

Layout과정과 같이 변경이 필요한 View들을 한 번에 처리한다.

 

이렇게 모든 Layer가 배치되고, 그려지게 되면 Layer tree를 렌더링 하기 위해 Render Server로 보내게 된다.

 

Render Prepare Phase

"Render Prepare Phase"는 모든 Layer Tree를 순회하여, GPU가 실행할 수 있는 선형 PipeLine을 준비한다.

부모 View서부터 자식 View 순으로 순차적으로 배치된다.

 

 

Render Execute Phase

"Render Execute Phase"는 전달된 선형 PipeLine을 통해 

GPU에서 최종 texture를 생성한다. 

 

Display Phase

완성된 Frame을 실제 Device 화면에 보여준다.

 

 

Parallel Render Loop

실제로는 다음과 같이 병렬적으로 돌아가

App Stage에서 Render Server Stage를 수행할 수 있다. 

 

 

Type of Hitches

이러한 Hitch에는 2가지 Type이 존재한다. 

  • Commit Hitches : Commit Phase에서 Hitch가 발생
  • Render Hitches : Render Execute Phase에서 Hitch가 발생

다음 포스팅에서 2가지 타입의 Hitch에 대해 자세하게 알아보자. 

 

 

Reference

https://developer.apple.com/videos/play/tech-talks/10855

'iOS > iOS' 카테고리의 다른 글

[iOS] Core Animation(1) - Concept  (0) 2024.03.05
[iOS] Render Loop & Hitch(2)  (1) 2024.02.24
[iOS] UIResponder(1)  (1) 2023.11.10
[iOS] Custom Drop Down  (1) 2023.10.31
[iOS] LocalDB(3) - Core Data CRUD  (0) 2023.10.25
복사했습니다!