Flutter Study

Flutter Impeller, skia Engine 에 관해서

cwdev 2024. 5. 23. 16:56

Flutter Impeller 

Flutter의 Impeller 렌더링 엔진은 Flutter 3.10 버전에서 iOS 용으로 기본 엔진으로 도입되었고, Android용으로는 Vulkan( 오버헤드가 적은 크로스 플랫폼 3D 그래픽스 및 컴퓨팅 API)을 지원하는 자이에서 사용할 수 있는 미리보기 버전이 Flutter 3.16에 도입되었습니다. 

Flutter Impeller란? 

Impeller는 Flutter의 "초기 버벅거림 발생" 문제를 해결하기 위해 처음부터 설계된 새로운 렌더링 엔진입니다. 기존 Skia 엔진과 달리 Impeller는 빌드 프로세스 중에 셰이더를 사전 컴파일하므로 가끔 문제를 일으킬 수 있는 런타임이 필요하지 않습니다. 

 

그래서 더 좋아진 효과로는

  • 예측 가능한 성능 : 사전 구축된 리소스 덕분에 일관된 프레임 속도를 즐기고 끊김 현상을 제거합니다.
  • 더욱 부드러워진 애니메이션 : 화면 전체를 아무런 문제 없이 미끄러지듯 움직이는 숨이 막히 정도로 부드러운 애니메이션을 감상.
  • 3D 가능성 : 2D가 핵심 초점으로 남아 있지만 Impeller는 Flutter 내에서 향후 3D 탐색을 위한 문을 엽니다. 

임펠러를 선택하는 이유?

  • 최신 GPU의 성능 활용: 뛰어난 렌더링 기능을 위해 차세대 그래픽 하드웨어를 이용
  • 향상된 사용자 경험 : 빠르고 반응성이 뛰어난 앱을 제공
  • 미래 보장형 개발 : 앱의 복자성에 맞춰 확장되고 잠재적인 3D 가능성을 수용하는 기술에 투자 

현재 상태 및 가용성

  • 임펠러는 현재 활발하게 개발 중.
  • iOS : Impeller는 Flutter 3.10 부터 모든 iOS Flutter 앱의 기본 렌더링 엔진.
  • Android : 2024.05.15 Flutter 3.22 출시와 함께 차세대 렌더링 엔진인 임펠러(Impeller)는 이제 Android에서 기능이 완성

 


Skia에서 버벅거림이 발생한 이유는? 

Skia에서는 컴파일 프로세스가 런타입에서 발생합니다.  렌더링 파이프라인은 실제 무엇가를 렌더링하는데 사용됩니다.

이로 인해 일반적으로 프레임이 예산을 초과하여 눈에 띄는 끊김 현상이 발생합니다. 

 

이해해야될 단어 - 셰이더, 렌더링 파이프라인 

셰이더 : GPU에서 실행되는 작은 프로그램. 각 픽셀이나 버텍스를 처리하는 역할.

-> Skia에서는 이러한 셰이더가 애플리케이션 실행 중 처음으로 필요할 때 컴파일됨.

-> 셰이더가 처음 필요할 때 컴파일되므로, 컴파일 시간이 걸리게 되어 해당 프레임의 렌더링이 지연될수 있음. 이로 인해 애플리케이션이나 인터페이스가 멈추거나 끊기는 현상이 발생

 

렌더링 파이프라인 : 이는 그래픽 화면에 그리는 전체 과정을 의미. 여기에는 그래픽 데이터를 처리하고, 셰이더를 적용하고, 최종적으로 모든 단계가 포함. 

 

Flutter의 렌더링 과정 

 

 

Flutter 로고에 대한 UI 코드를 변경했을때, Flutter 프레임워크에서 위젯 트리렌더링 객체 트리(Render Tree)의 지원을 받습니다.

Render Tree에는 위젯을 실제로 레이아웃하고 그리는 방법에 대한 지침이 포함되어 있습니다. 이러한 지침은 엔진에 제공되며 display List 라는 간단한 명령의 정렬된 목록에 저장됩니다. 

 

Display List - 렌더 객체는 display list에 자신이 그릴 그래픽 요소에 대한 고급 명령어를 기록. 이 명령어는 GPU가 이해할 수 있는 형태로 변환될 수 있는 지침 (ex. 이미지 렌더 객체는 "이 위치에 이 크기의 이미지를 그려라" 라는 명령어를 display list에 추가 ) 

 

엔진은 사용 가능한 렌더링 중 하나의 Impeller 또는 Skia 를 사용하여 이 표시 목록을 표면 텍스쳐 또는 화면에 표시 할수 있는 비트맵에 그리는 작업을 담당. 표시목록의 모든 항목을 렌더링하는데 사용할 수 있는 렌더 파이프라인이라는 항목 모음을 설정하여 GPU를 활용.

 

 

 

Impeller 아키텍쳐 

 

 

위 렌더링 과정들을 impeller 엔진에서 보면, Aiks에서 Draw Path, Draw Image from displaylist 와 같은 고급 명령을 가져와 이를 엔터티(Entity)라고 하는 더 간단하고 독립적인 작업으로 바꾼다. 

 

엔터티(Entity) 의 역할 

  • 그래픽 요소 표현 - 엔터티는 화면에 표시할 그래픽 요소(ex. 이미지 ,텍스트, 도형등)를 표현합니다. 각각의 엔터티는 특정 그래픽 요소를 렌더링하기 위한 모든 필요한 정보를 포함하고 이습니다. 
  • 속성 저장 : 엔터티는 렌더링에 필요한 속성들을 저장합니다. 예를들면 위치, 크기, 색상, 변환 정보등을 포함합니다. 
  • 렌더링 지침 제공 - 엔터티는 실제 렌더링 과정에서 GPU에게 어떤 작업을 수행해야 하는지 지침을 제공합니다. 이는 셰이더 프로그램(GPU에서 실행되는 작은 프로그램) 이 어떻게 동작해야 하는지, 어떤 텍스쳐를 사용해야 하는지 등을 포함합니다. 

고급 명령을 엔터티(Entity)로 바꾸는 과정

 

다시 또 정리를 하자면, 위젯트리는 렌더트리로 변환되고 각 렌더 객체들은 화면에 어떻게 그려질지를 정의합니다. 레이아웃단계와 페인트 단계를 걸쳐서 DisplayList에 명령어를 추가합니다. DisplayList에는 RenderConstrainedBox, RenderDecoratedBox, RenderPadding과 같은 명령어들이 추가되고 이러한 DisplayList를 Flutter 프레임워크가 엔진에게 전달합니다. 

엔진은 Aiks 를 이용해서 DisplayList를 가져오고 이를 엔터티(Entity)라고 하는 더 간단하고 독립적인 작업으로 바꿉니다. 

엔터티안에는 엔터티는 화면에 표시할 그래픽 요소,엔터티는 렌더링에 필요한 속성들 위치,회전 및 배율을 인코딩하는 변환 행렬과 같이 모두 단일 그리기 작업에 필요한 여러 속성이 포함되어 있습니다. 모든 엔터티에는 엔터티를 그리는 데 필요한 실제 GPU 명령이 포함된 콘텐츠 개체도 할당됩니다.

 

 

 

 

하드웨어 추상화 계층(Hardware Abstraction Layer, HAL)은 Flutter의 렌더링 파이프라인에서 중요한 역할을 하며, 다양한 플랫폼의 그래픽 API와 통신하는 역할을 합니다.

 

HAL은 iOS의 Metal, Android의 Vulkan, OpenGL 등 다양한 그래픽 API와 통신하는 공통 인터페이스를 제공.
(다양한 표준 그래픽 API를 통해 그래픽 드라이버와 통신하는 얇은 추상화)

 

를 통해 Flutter 애플리케이션은 특정 플랫폼에 종속되지 않고 일관된 렌더링을 수행할 수 있습니다. HAL은 그래픽 드라이버와 통신하여 GPU에게 정확히 어떤 작업을 수행해야 하는지 지시. 이는 다양한 플랫폼의 그래픽 API에 대한 직접적인 호출을 추상화하여, 상위 레벨의 코드가 특정 API에 의존하지 않도록 합니다.

 

드웨어 추상화 계층은(HAL)은 엔터티에 포함된 명령어를 플랫폼별 그래픽 API 호출로 변환하고, 실제로 사용하려는 셰이더가 포함된 렌더 파이프라인을 실행하도록 GPU에 지시함으로써 자체적으로 그려집니다.

 

리마인드 :

(셰이더 : GPU에서 실행되는 작은 프로그램. 각 픽셀이나 버텍스를 처리하는 역할.)

(렌더링 파이프라인 : 이는 그래픽 화면에 그리는 전체 과정을 의미)

 

렌더파이프라인이 GPU에게 무엇을 해야할지 정학하게 알려주고, 각 콘텐츠는 하드웨어 추상화 계층을 사용하여 실제로 사용하려는 셰이더가 포함된 렌더 파이프라인을 실행하도록 GPU에 지시함으로써 자체적으로 그려집니다. 이러한 명령은 그래픽 API를 사용하여 실행된 다음 결과 텍스쳐가 화면에 표시됩니다. 

 

이러한 셰이더와 렌더 파이프라인도 GPU가 실행할 수 있는 명령으로 컴파일되어야 합니다. 그리고 이 과정은 매우 비용이 많이 듭니다. Skia에서는 이 컴파일 프로세스가 프레임에서 바로 런타임에 발생합니다. 프이프라인은 실제로 무엇가를 렌더링하는 데 사용되어야 합니다. 이로 인해 일반적으로 프레임이 예산을 초과하여 눈에 띄는 끊김 현상이 발생합니다.

 

 

 

Impeller는 이 컴파일 중 가장 비용이 많이 드는 부분을 미리 수행하여 이 문제를 크게 개선합니다.

Impeller 오프라인 셰이더 컴파일러를 사용하여 Impeller의 모든 셰이더가 번들로 컴파일 됩니다. 

Impeller의 아키텍처를 살펴보면서 Flutter가 실제로 그래픽 렌더링 방법을 완벽하게 제어할 수 있다는 것을 확인했습니다.

Flutter는 플랫폼별 UI 툴킷을 사용하지 않기 때문에 플랫폼별 UI 툴킷에 의해 부과된 아키텍처 또는 다자인 제한의 적용을 받지 않습니다.

대신 Flutter의 엔진은 그래픽 드라이버와 직접 통신합니다. 이를 통해 모든 플랫폼에서 정확히 원하는 방식으로 작동하는 풍부하고 독특한 앱을 구축할 수 있습니다. 이러한 종속성 부족으로 인해 Flutter는 자동차 대시보드, IoT, 디지털 간판과 같은 임베디드 사용 사례를 위한 훌륭한 솔루션이 됩니다.

 

 

https://simi.studio/en/flutter-impeller/

 

Flutter Impeller: A New Era of Smoothness and Performance

Impeller is a brand new rendering engine designed from the ground up to address Flutter's 「early-onset jank」 issue. Unlike the traditional Skia engine, Impeller pre-compiles shaders during the build process, eliminating the need for runtime compilation

simi.studio

https://docs.flutter.dev/perf/impeller

 

Impeller rendering engine

What is Impeller and how to enable it?

docs.flutter.dev

https://medium.com/flutter/io24-5e211f708a37

 

Landing Flutter 3.22 and Dart 3.4 at Google I/O 2024

Major milestones for Flutter web apps, graphics performance upgrades, productivity experiments, and more

medium.com