Android Vulkan 官宣转正并统一渲染堆栈 ,这对 Flutter 又有什么影响?

虽然从 2016 年的 7.0 开始 Android 就已经支持 Vulkan ,并且在之后 Vulkan 逐步作为首选 GPU 接口,但是现在从 2025 开始, Vulkan 将正式官宣成为 Android 上的官方图形 API

那「转正」后和之前有什么区别?核心就是 Vulkan 将正式作为 Android 的唯一 GPU 硬件抽象层 (HAL),Google 会要求所有应用和游戏都必须基于 Vulkan 来实现,包括:游戏引擎、middleware 和 HWUI/Skia/WebGPU/ANGLE 等 layered API:

这里就不得不说 ANGLE (Almost Native Graphics Layer Engine) ,虽然 Google 打算强制开发者使用 Vulkan ,但是让大家全部迁移明显不现实,毕竟 Vulkan 和 OpenGLES 的差异还是很大的,而这时候 ANGLE 就开始体现它作用。

ANGLE 作为兼容层,它支持让 GLES 应用运行到 Vulkan ,ANGLE 通过将 GLES API 调用翻译为 Vulkan API 调用,从而让 GLES 能够兼容运行到 Vulkan ,而事实上 ANGLE 在 Android 10 开始就开始尝试支持 Vulkan,但是从 Android 15 之后,新的 Android 设备将开始转为仅通过 ANGLE 支持 OpenGL

其实做出这个决定也挺合理,从数据上看,目前超过 85% 的活跃 Android 手机都已经支持 Vulkan,而基于 Unity 引擎构建的新 Android 游戏里超过 45% 使用 Vulkan,所以 Vulkan only 确实是一个必然的选择。

那为什么 Google 会想要替换到 OpenGL?主要也是因为 OpenGL 存在很多历史问题,例如:

  • OpenGL 默认是单线程模型,而 Vulkan 中引入了 Command Buffer ,每个线程都可以往 Command Buffer 提交渲染命令,可以更方便利用多核多线程的能力
  • OpenGL 很大一部分支持需要驱动的实现,OpenGL 驱动包揽了一大堆工作,在简化上层操作的同时也牺牲了性能;而 Vulkan 里驱动不再负责跟踪资源和 API 验证,虽然这提高了框架使用的复杂度,但是性能得到了大幅提升
  • 还有 swapchain 差异,后面我们会聊到。

而对于即将到来的 Android 版本:

  • Android 16 将要求一些较新的设备对某些 App 使用 ANGLE
  • Android 17 将要求新设备为大多数 App 使用 ANGLE

也就是 Android 17 开始,除了特定列表中的 App 外,所有应用都需要使用 ANGLE

另外,虽然 Vlukan 的一致性比起 OpenGL 好很多,但是为了进一步提高 Android 上的 Vulkan 实际可用功能一致性,Google 推出了适用于 Android 的 Vulkan 配置文件 (VPA)。

VPA 是芯片组必须支持的 Vulkan 功能的集合,只有适配了,才能通过 Google 针对特定 Android 版本的认证要求,例如 Android 16 的 VPA 要求芯片组至少支持这些 Vulkan 功能:github.com/KhronosGrou...

通过强制支持较新版本的 Vulkan,也会加速淘汰较旧的 GPU 设备,因为使用这些较旧 GPU 的设备会不允许更新到较新的 Android 版本,这也意味着随着时间的推移, Vulkan 在未来的一致性会越来越高。

除此之外,Google 还和 Unity Technologies 合作,让 Vulkan 和 Unity 游戏引擎的集成变得更加容易,从而进一步降低 PC 游戏移植到 Android 的难度

另外,谷歌还与联发科达成合作,为联发科芯片提供 Android 动态性能框架 (ADPF),支持让开发人员根据设备的热状态实时调整游戏的性能需求:

最后,Java/Kotlin 开发者后续可能无需切换到 C/C++ 和 NDK 来直接访问 Vulkan,未来 Java/Kotlin 开发者也许可以通过 Java/Kotlin 下利用 WebGPU 来"直接"体验 Vulkan 场景,从而做到相对 "直接" 的 GPU 访问:

所以,到这里有没有一种感觉:就像当年 Apple 全面转向 Metal 的感觉,现在 Google 终于开始也跟上这个步伐

Flutter

那么这些 Flutter 有什么影响?答案肯定就是 All In Impeller ,这是 Flutter 正在做的事情,当然这也是一个「充满坎坷」的过程,因为 Android 的碎片化让 Impeller 在 Android 的落地比 iOS 复杂很多。

比如 Flutter 3.29 才发布了 Android 平台正式全面启用 Impeller ,但是 3.29.2 版本就开始「回退」,原因是 Impeller 在某些不支持 Vlukan 的低版本设备上使用 Impeller GLES 作兼容时会 Crash ,所以只能暂时再次转为 Skia GLES :

其实这也一定程度体现了 OpenGL 在兼容上的难度。。。。。

甚至在之前我们聊过的 《全新 PlatformView 实现 HCPP》 支持上,也可能需要考虑针对 OpenGLES 增加一个 AHB swapchain 来帮助没有 Vulkan 的设备支持 HCPP :

甚至在 Vulkan 相关的 swapchain 支持上, AHBSwapchainVK 实现也并非在所有 Android 版本上都可用,如果不支持还需要会回退到 KHR swapchain ,例如:

  • API 26 之前不支持 AHB
  • AHB 某些功能和 API ,比如 AHardwareBuffer_isSupported 需要 API 29

所以可以看到,就算存在 Vulkan 场景,在 Android 上 Impeller 也需要根据实际场景使用不同支持 ,说到这里可能大家就有点懵,swapchain 是什么?AHB 又是什么?这里顺便简单介绍下

什么是 swapchain ? swapchain 简单说就是一种用于管理多个缓冲区的机制,从而确保平滑渲染和显示画面,进而防止画面撕裂,比如 swapchain 通常会有双缓冲或三缓冲,通过实现类似一个缓冲区显示的同时,另一个缓冲区正在准备渲染一下帧。

通俗又不严谨的说法:现在的 GPU 渲染效率很高,而系统显示的速度跟不上 GPU 渲染的速度,所有可以通过多重 buffer 的作用,提前在 GPU 渲染画面,等待提交,而提交给系统显示的过程中,就是在 buffer 之间进行交换 (Swap)。

所以也可以理解为:swapchain 是一系列图像队列,队列会顺序交替将图像提交到系统显示

所以,其实当你在 Android 启用 Impeller 后会发现,如果在特定设备上出现如下图所示这种画面撕裂的问题,一般首先会怀疑 swapchain 问题,这里其实就是 Impeller 使用了 AHB swapchain 的 bug 导致:

那么 AHB(Android Hardware Buffer) 又是什么?简单说,AHB 是 Android 上一种高效共享缓冲区的机制,属于进程间高效共享缓冲区的场景,支持零拷贝操作,而 AHB 可以绑定到 EGL/OpenGL 和 Vulkan ,从而适合跨进程图形数据共享。

前面我们说过,swapchain 是一系列图像队列,队列会顺序交替将图像提交到系统显示,而如果配合 AHB ,就可以起到性能优化的作用,因为 AHB 可以做到零拷贝意味着数据在进程间共享时无需复制 ,也就是在高帧率应用里,渲染进程生成的帧可以直接由显示进程使用而无需额外拷贝。

也就是,当应用渲染新帧时,AHB 确保显示进程能立即访问。

那么回到 Vulkan,对于 Vulkan 来说 swapchain 就是它的标准实现,所以它本来就是基于 swapchain 模式工作,但是由于 Android 平台存在 AHB ,所以是否使用 AHB 来加速性能对于 Impeller 就是一个需要衡量的情况:

至少目前看来 AHB 确实给 Impeller 带来不少问题。

所以简单总结下,对于 Vulkan 而言:

  • 默认有 vkSwapchainKHR 的相关 swapchain 实现
  • Android 上通过 AHBSwapchainVK 自定义可以让 Vulkan 使用 AHB 来得到性能提升,对应逻辑就是 issue 和代码里经常提到的 SurfaceControl AHB Swapchain

而对于 OpenGL 来说,它并没有标准的 swapchain 实现 ,所以如果 HCPP 模式想要支持 AHB swapchain,也就是需要上面所说的自定义来完成。

那么从 Flutter 角度看,Vulkan 和 OpenGL 的同时存在,确实也让 Impeller 在 Android 上的稳定性成本大大提高,那么未来 ANGLE 的强势介入,也许就不在会再有这种问题存在。

也许到那个时候,Flutter GPU 和 sence 场景,也能开始正式落地。

参考资料

相关推荐
庸俗今天不摸鱼17 分钟前
【万字总结】前端全方位性能优化指南(三)
前端·性能优化·gpu
前端南玖27 分钟前
深入理解Base64编码原理
前端·javascript
Cao_Shixin攻城狮29 分钟前
Flutter项目升级Xcode 16.2之后编译问题
flutter·xcode
仙魁XAN29 分钟前
Flutter 学习之旅 之 flutter 使用 SQLite(sqflite) 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装
数据库·flutter·sqlite·sqflite·本地化数据
aircrushin29 分钟前
【PromptCoder + Trae 最新版】三分钟复刻 Spotify 页面
前端·人工智能·后端
木木黄木木33 分钟前
从零开始实现一个HTML5飞机大战游戏
前端·游戏·html5
NoneCoder35 分钟前
工程化与框架系列(30)--前端日志系统实现
前端·状态模式
计算机毕设定制辅导-无忧学长1 小时前
HTML 基础夯实:标签、属性与基本结构的学习进度(一)
前端·学习·html
斯~内克1 小时前
深度解析ECharts.js:构建现代化数据可视化的利器
前端·信息可视化·echarts