当前位置: 首页 > news >正文

Impeller-Flutter的新渲染引擎

Impeller是什么?它本质上是怎样运行的?

Impeller是Flutter的新的渲染引擎,直到现在Flutter正在用一个叫做Skia的渲染引擎。

问题是Skia不是为了Flutter量身定做的。它有为范围广阔的设备构建的一大堆的渲染特性,这意味着它并不总是为了Flutter的需求优化。

进入到Impeller,Flutter的新渲染器。我们构建Impeller来专门专注在Flutter应用的渲染需要。

主要目标是为了消除你的应用中的卡顿和任何磕磕巴巴。

这样对于你的终端用户来说将总会感觉良好。

对于不是图形工程师的人来说,可能会困惑,渲染器是什么?

渲染器是一个软件,帮助你转变你的UI代码到你实际上在屏幕上看到的像素点。

在Flutter框架中,你的部件树被一个渲染对象的树来处理。

渲染对象包含如何来布局(Layout)和绘制(Paint)部件的指令。

这些指令被给到引擎,并且存储在一个简单命令的有序列表中,称为显示列表。

这是事情变得有趣的地方。

引擎负责使用可用的渲染器之一,Impeller或者是Skia,来绘制这个显示列表到一个表面纹理上(Surface Texture)。或者是一个网格的像素值,可以被显示在屏幕上。

它利用GPU通过设置一系列的事情,称为渲染管线。

可以被使用来渲染显示列表中的一切东西。现在来进入细节。

Tessellation(曲面细分)

在我们能够使用一个渲染管线,我们首先需要得到被显示列表绘制的所有的path。

tessellate(细分)它们到一些列的三角形中。

那么三角形上的每个(vertex)或者是(point)被传递到vertex shader中。

shader只是一小块的代码,在图形设备上运行。

shader是内部的,意味着它们是Flutter引擎代码库的一部分。

但是Flutter开发者可以创作自己的shader,这个晚一些提及。

Vertex Shader接收组成Flutter Logo的顶点,移动它们到我们实际上希望看到的屏幕位置。

现在Flutter Logo在正确的位置了,我们开始迭代所有的三角形。

现在拉近放大一些。对于每个三角形来说,我们弄清楚在它内部具体的像素。这被称为rasterization(光栅化)。接着对于这些方形的每一个,一些检查被运行,来决定我们是否真的需要为它计算出一个颜色值。

对于Impeller来说,这些检查是很重要的。

现在,所有在三角形中的这些像素被传递到一个fragment shader上。

fragment shader是另一个代码片段,但是这次它接收vertex shader的输出,并且计算一个颜色。

正如之前所提到的,Flutter开发者可以重写它通过创建自己的shader,来创建很整洁的特效,使用fragment program API。

无论如何,返回到我们的渲染管线上。

最后,输出颜色被与已经绘制的颜色blended(混合)。

在这个情况下,我们的混合是很简单的,只需要替换颜色。

这就是东西如何在GPU上渲染的。

这些渲染管线是如何在Impeller上实现的,

Impeller有一个层级的架构,每一层使用它下面的一层来完成它的工作。

Flutter部件如何转变到一个显示列表上的。

在这个例子中,显示列表仅仅包含一些操作来为它放置位置到屏幕的中心,除此之外,还有四个DrawPathOps。

Logo中的每一个四边形一个。我们拿到显示列表并且使用Impeller来绘制它。

首先,所有的显示列表操作被发送到一个叫做Aiks的东西那里。

Aiks是Impeller的最上层,主要由Canvas绘制API组成。

随便说下,Aiks是Skia的反过来。

Aiks的任务是接收高阶的命令,例如从显示列表中接收DrawPath和DrawImage,并且把它们转变成为更简单的,自包含的绘制操作称为entities。

下一层是Entities Framework。在我们的例子中,从Flutter logo中的四个DrawPathOps,每一个得到了一个自己的Entity。每个Entity包含每一个单独绘制命令需要的一堆属性,例如一个编码了平移,旋转和缩放的Transformation Matrix(变换矩阵)。

每个Entity也有一个Contents对象分派给它,它包含了绘制Entity所需要的实际的GPU指令。

有SolidColor,Images,Gradients,Text,Clips,一切Fluuter可以绘制的东西。

有时,我们甚至有多个特别的Contents使用不同的拥有不同性能特征的算法来绘制相同的东西。

这样Aiks可以挑选和选择最有效率的渲染算法。

在这样的情况下,Flutter的四个四边形仅仅被纯色(Solid Color)填充。

所以每个实体得到一个SolidColorContents指派到它们。

现在,我们需要详细说明这些指令,以一种GPU可以理解的方式。

因为Flutter APP可以运行在一堆不同的平台上,Impeller需要某种类型的转换层来与GPU交互。

这一层在Entities Framework下,叫做硬件抽象层(Hardware Abstraction Layer)。

这一层是一个薄的抽象,和图形驱动交互,通过各种标准的图形API,例如IOS上的Metal,Android上的Vulkan。

现在我们准备好了到底告诉GPU做什么。

记得那些渲染管线吗?

Vertex Shader  ->  Rasterazation -> Stencil Test -> Fragment Shader -> Blending

这是它们参与进来的地方。

每个Contents使用硬件抽象层来绘制自己通过指令GPU执行渲染管线,包含我们实际想用的shaders。

那些命令通过图形API被执行,接着结果纹理显示到了屏幕上。

但是,还有一个巨大的细节没有提及。那些Shader和渲染管线也需要编译成GPU可以执行的指令。这个过程非常昂贵。

在SKia中,这个编译过程在运行时发生。正好在这一帧上,管线实际上需要被使用来渲染一些事情。这通常导致这一帧远远超过预算(Go Way Over Budget),导致一个明显的卡顿。

我们通常提到这个问题成称为Shader编译卡顿(shader compllation jank)。Impeller很大的改善了这个问题,通过提前执行最昂贵的部分。

这是Impeller的最后一个组件出现。

当Flutter引擎被构建时,所有Impeller的Shader被编译成捆,使用Impeller的离线Shader编译器,称为(Impeller Scene)。

在走过Impeller架构中,你已经看到Flutter对于它如何渲染图形有完全的控制。Flutter不受平台专用的(platform-specific)UI工具包的规定支配,因为Flutter甚至不使用它们。取而代之的是,Flutter引擎直接与图形驱动交互。这允许你构建丰富独特的应用表现得像你在任何的平台上想要的那样。缺少依赖也使得Flutter对于嵌入式的用例,例如汽车仪表板,Iot,数字标牌是一个好的解决方案。

现在你有了一个本质上发生的事情的认识,让我来强调做出一些关键的架构决策,它们使得Impeller对于Flutter应用是一个好的渲染器。一个Impeller提供的巨大的好处是通过编译那些称为Shader 的程序来减少卡顿。为了做这件事情,Impeller并不和Skia一样生成Shaders。取而代之的是,Impeller有一套提前编译的手写的Shaders。

但是,你可以担心初始化一堆预编译的Shaders可能意味着更慢的启动时间,或者是更大的Flutter应用大小。为了避免这个,Impeller使用选择的渲染技术,相比较于Skia动态生成的许多专用的Shader来说,利用一个更小更简单的Shader集合。

另外一个原因为什么Impeller提供了优秀的性能是实现抗锯齿的方式。抗锯齿是消除绘制元素-锯齿边的艺术,所以它们看上去更加的自然。Impeller使用MSAA来执行这个工作,它由Flutter支持的所有的设备上,它执行的成本低,在现代的移动设备上产生出优秀质量的结果。

另一个我们专注于的事情是Impeller如何实现剪裁(Clipping)。当渲染部件时,Flutter频繁的使用剪贴蒙板(clip masks)来剪下形状,所以这个步骤的效率很重要。Impeller特别得采用一个步骤利用硬件的特性来确保剪裁非常的快速。记得之前提到的特殊检查吗?一个称为是模板测试(Stencil Buffer)。现在我们不进入太多的细节中,但是基本上的,当Impeller为剪裁绘制像素时,它告诉GPU检查模板(stencil),过滤掉所有不是填充区域部分的所有的像素。这意味着即使一个裁剪非常的复杂,像这个使用来创建这些万花筒动画,它仍然是一个开销便宜的操作。所以我们可以看到一些非常巨大的性能提升。在左边是Flutter的Impeller之前,每秒7帧渲染。在右边Impeller以每秒60帧渲染。

我们已经谈到了Impeller的一些设计选择,对于大部分的Flutter开发者来说,这意味着你将看到更多可预测的帧数当你使用Flutter时。但是对于那些感兴趣更加高级的渲染用例的人,Impeller也旨在提供一个发射台来解决其它的图形需要。展示了一个3D场景图,直接在Impeller的硬件抽象层之上,称为Impeller Scene。Impeller Scene有自己的Contents在Entity Framework上。它绘制3D对象使用相同种类的渲染管线。

要点:

Buffer Management        Skeleton Animation     Ray Casting

Deferred Rendering       Ray  Tracing     Anti Aliasing       PBR

Signed Distance Fields       Reflection Probes      Post  Processing

Rasterization                    HDR                                  Shadows

现在,开始构建渲染器有很多重大的决定。尽管我们可以构建3D渲染器,有用并且做出聪明的权衡,没有一个渲染器可以完美的解决每一个用例。所以,下一步我们积极地进行实验。所以Flutter社群中的任何人可以构建自己的渲染包,并且创建自定义的渲染管线,并且无缝地和剩余的组件系统集成。

相关文章:

Impeller-Flutter的新渲染引擎

Impeller是什么?它本质上是怎样运行的? Impeller是Flutter的新的渲染引擎,直到现在Flutter正在用一个叫做Skia的渲染引擎。 问题是Skia不是为了Flutter量身定做的。它有为范围广阔的设备构建的一大堆的渲染特性,这意味着它并不总…...

python 面试算法题

1.第一题 题目描述:给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。 s 的 旋转操作 就是将 s 最左边的字符移动到最右边。 例如, 若 s abcde,在旋转一次之后结果就是bcdea 。 示例一: 输入: s &quo…...

Python中的yield关键字

基本概念 yield 是 Python 中的一个关键字,主要在定义生成器函数时使用。使用 yield 的函数在调用时返回一个特殊的迭代器,称为生成器。不同于常规的函数返回一个单一的值(如数字、字符串或其他对象),带有 yield 的函…...

怎么压缩pdf文件?分享缩小pdf文件的简单方法

在我们的日常生活和工作中,往往需要处理大量的PDF文件,而很多时候这些文件的大小会成为传输和存储的难题。为了解决这个问题,下面我们将介绍三种方法来压缩PDF文件,一起来看看吧~ 一、嗨格式压缩大师 首先,最简单也是…...

51单片机可调幅度频率波形信号发生器( proteus仿真+程序+原理图+报告+讲解视频)

51单片机可调幅度频率信号发生器( proteus仿真程序原理图报告讲解视频) 讲解视频1.主要功能:2.仿真3. 程序代码4. 原理图4. 设计报告5. 设计资料内容清单&&下载链接***[资料下载链接](https://docs.qq.com/doc/DS1daV1BKRXZMeE9u)*** 51单片机可…...

Vuex的介绍

介绍 :::warning 注意 在阅读此文章之前请确保你已经掌握了组件中的选项 data、计算属性 computed、methods 方法等相关知识。 ::: 什么是 Vuex? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以…...

mysql基础语法速成版

mysql基础语法速成版 一、前言二、基础语法2.1 数据库操作2.2 MySQL数据类型2.3 表操作2.3.1 表的创建、删除,及表结构的改变2.3.2表数据的增删改查2.3.4 like模糊查询2.3.5 UNION 操作符2.3.6 order by排序2.3.7 group by分组2.3.8 join连接2.3.9 null处理2.3.10 m…...

Docker镜像 配置ssh

安装 1.安装ssh 2.设置root密码 RUN echo root:123456 | chpasswd 3.设置sshd config RUN echo Port 22 >> /etc/ssh/sshd_config RUN echo PermitRootLogin yes >> /etc/ssh/sshd_config4.设置开机启动 RUN mkdir /var/run/sshd #没有这个目录,s…...

12.2 实现键盘模拟按键

本节将向读者介绍如何使用键盘鼠标操控模拟技术,键盘鼠标操控模拟技术是一种非常实用的技术,可以自动化执行一些重复性的任务,提高工作效率,在Windows系统下,通过使用各种键盘鼠标控制函数实现动态捕捉和模拟特定功能的…...

《DevOps 精要:业务视角》- 读书笔记(七)

DevOps 精要:业务视角(七) DevOps历程什么是企业体系的DevOps?DevOps的目标是什么? DevOps的知识体系规范敏捷持续交付IT服务管理以TPS理念为基础 DevOps团队角色流程主管(Process Master)服务主管&#xf…...

【随想】每日两题Day.12(实则一题)

题目:15. 三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不…...

基于复旦微JFM7K325T FPGA的高性能PCIe总线数据预处理载板(100%国产化)

PCIE711是一款基于PCIE总线架构的高性能数据预处理FMC载板,板卡采用复旦微的JFM7K325T FPGA作为实时处理器,实现各个接口之间的互联。该板卡可以实现100%国产化。 板卡具有1个FMC(HPC)接口,1路PCIe x8主机接口&#x…...

什么是原型链(prototype chain)?如何实现继承?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

RabbitMQ 5种工作模式介绍和Springboot具体实现

RabbitMQ有5中工作模式:简单模式、工作队列模式、发布/订阅模式、路由模式和主题模式 简单模式(Simple Mode) 简单模式是最基本的工作模式,也是最简单的模式。在简单模式中,生产者将消息发送到一个队列中,…...

C++ - 可变模版参数 - emplace相关接口函数 - 移动构造函数 和 移动赋值运算符重载 的 默认成员函数

可变模版参数 我们先来了解一下,可变参数。可变参数就是在定义函数的时候,某一个参数位置使用 "..." 的方式来写的,在库当中有一个经典的函数系列就是用的 可变参数:printf()系列就是用的可变参…...

总结三:计算机网络面经

文章目录 1、简述静态路由和动态路由?2、说说有哪些路由协议,都是如何更新的?3、简述域名解析过程,本机如何干预域名解析?4、简述 DNS 查询服务器的基本流程是什么?DNS 劫持是什么?5、简述网关的…...

服务器数据恢复-VMWARE ESX SERVER虚拟机数据恢复案例

服务器数据恢复环境: 几台VMware ESX SERVER共享一台某品牌存储,共有几十组虚拟机。 服务器故障: 虚拟机在工作过程中突然被发现不可用,管理员将设备进行了重启,重启后虚拟机依然不可用,虚拟磁盘丢失&#…...

COCI 2021-2022 #1 - Set 题解

思路 我们将原题中的数的每一位减一,此时问题等价。 下面的异或都是在三进制下的异或。(相当于不进位的加法) 我们考虑原题中的条件,对于每一位,如果相同,则异或值为 0 0 0,如果为 1 1 1&a…...

分享40个极具商业价值的chatGPT提问prompt

原文:分享40个极具商业价值的chatGPT提问prompt | 秋天的童话博客 1、分析并改善定价策略 提示: "分析我当前的[插入产品或服务]定价策略。提出改进建议,并帮助我制定新的定价策略,以最大化利润和客户满意度。" Analyze and Imp…...

一文搞懂到底什么是元宇宙

一、背景 2021年,“元宇宙”是科技界的开端。 2021”元宇宙”这个词在Facebook更名后被点燃了,无疑是21世纪科技界最爆的起点。各式各样的定义、解读都出现了,有人说它是炒作,甚至是骗局,但也有人说它就是互联网的未…...

【重拾C语言】六、批量数据组织(四)线性表—栈和队列

目录 前言 六、批量数据组织——数组 6.1~3 数组基础知识 6.4 线性表——分类与检索 6.5~7 数组初值;字符串、字符数组、字符串数组;类型定义 typedef 6.8 线性表—栈和队列 6.8.1 栈(Stack) 全局变量 isEmpty() isFull…...

力扣刷题-哈希表-一个字符串是否能够由另一个字符串中的字符组成

383 赎金信 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。ransomNote 和 magazin…...

Android使用AOP切面编程

在Android应用程序中,AOP可以被用于许多不同的场景,例如日志记录、权限控制、性能分析等。下面是一个简单的例子,说明如何在Android应用程序中使用AOP切面编程。 首先,我们需要在应用程序中引入AspectJ库。我们可以使用Gradle来完…...

Flutter学习笔记

此篇文章用来记录学习Flutter 和 Dart 相关知识 零.Dart基本数据类型 Dart 是一种静态类型的编程语言,它提供了一系列基本数据类型,用于存储和操作不同种类的数据。以下是 Dart 中的一些基本数据类型以及它们的详细介绍: 1. 整数类型&#…...

软件生命周期中的概念设计和详细设计的主要任务是什么

基础概念 在软件生命周期中,概念设计和详细设计是软件设计阶段中的两个重要环节。 概念设计阶段的主要任务是从业务需求出发,将系统的基本概念、主要功能和关键特性进行抽象和定义。概念设计旨在确定系统的整体架构和关键模块,包括以下主要…...

大数据学习(2)Hadoop-分布式资源计算hive(1)

&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博>主哦&#x…...

深入探究HTML表单与JavaScript的关系

深入探究HTML表单与JavaScript的关系 引言 HTML表单是网页中数据收集的重要工具,而JavaScript则充当着这些数据的处理者和控制者的角色。二者之间的关系非常紧密,共同构成了现代Web应用中用户交互的基础。在这篇博客中,我们将详细地解析HTM…...

关于Jupyter notebook 创建python3 时进去不能重命名问题及不能编程问题

首先写这篇博客时,已经被这个问题折磨了三天,看了很多博客,其实解决这个问题的关键就是要么没有下pyzmq或者等级太高,要么等级太低,首先我会按照我思路来。 问题如图: 1.自动换行 2.不能重命名 我的解决办…...

一些可以用代码绘制流程图的工具

代码绘制流程图的工具有很多,以下是一些常用的工具: Mermaid:Mermaid 是一个基于 Markdown 的图表语言,可以生成各种类型的图表,包括流程图、时序图、甘特图等。Mermaid 可以使用 JavaScript 或 TypeScript 进行编写,可以通过 Node.js 运行。Graphviz:Graphviz 是一个开…...

Centos中清除因程序异常终止,导致的残留的Cache/buff_drop_caches命令---linux工作笔记063

我这里因为nifi程序背压设置的不合理,导致,内存和CPU消耗过高,系统崩溃,但是重启NIFI以后,发现 对应的执行top命令,看到,系统的buff/cache 依然没有减少,说明内存被浪费了,残留在这里没有被回收. 用这个办法执行这个命令; linux会自动触发清理,但是只有在内存不够用的时候才会…...