JEP 382:新的 macOS 渲染管道
总结
使用 Apple Metal API 实现 macOS 的 Java 2D 内部渲染管道,作为现有管道的替代方案,现有管道使用的是已弃用的 Apple OpenGL API。
目标
- 为 Java 2D API 提供一个使用 macOS Metal 框架的全功能渲染管道。
- 在 Apple 从未来版本的 macOS 中移除已弃用的 OpenGL API 时做好准备。
- 确保新管道对 Java 应用程序的透明性。
- 确保实现与现有 OpenGL 管道的功能等价。
- 在选定的实际应用程序和基准测试中提供与 OpenGL 管道一样好或更好的性能。
- 创建一个符合现有 Java 2D 管道模型的简洁架构。
- 与 OpenGL 管道共存,直到其过时。
非目标
- 目标并不是移除或禁用现有的 OpenGL 管道。
- 目标并不是添加任何新的 Java 或 JDK API。这些都是内部实现。
动机
两个主要因素促使在 macOS 上引入新的基于 Metal 的渲染管道:
-
Apple 于 2018 年 9 月在 macOS 10.14 中弃用了 OpenGL 渲染库。macOS 上的 Java 2D 完全依赖 OpenGL 作为其内部渲染管道,因此需要一种新的管道实现。
-
Apple 声称 Metal 框架(他们对 OpenGL 的替代品)具有更优的性能。对于 Java 2D API 来说,通常情况下确实如此,但也有例外。
描述
大多数图形化的 Java 应用程序都是使用 Swing UI 工具包编写的,它通过 Java 2D API 进行渲染。在内部,Java 2D 可以使用软件渲染加上到屏幕的位块传输(blit),或者可以使用特定于平台的 API,例如 Linux 上的 X11/Xrender、Windows 上的 Direct3D 或 macOS 上的 OpenGL。这些特定于平台的 API 通常比软件渲染提供更好的性能,并且通常可以减轻 CPU 的负担。Metal 是用于此类渲染的新的 macOS 平台 API,取代了已弃用的 OpenGL API。(这个名字与 Swing 的 “Metal” 外观感觉没有任何关系;那只是一个巧合。)
我们创建了大量新的内部实现代码来使用 Metal 框架,正如我们已经为其他平台特定的 API 所做的那样。虽然新代码很容易融入现有的框架,但它在图形硬件的使用上更加现代化,利用了着色器而非固定功能管线。这些更改仅限于 macOS 特定的代码,即使在那里,也只有少量在 Metal 和 OpenGL 之间共享的代码被更新。我们没有引入任何新的 Java API,也没有更改任何现有的 API。
Metal 管线可以与 OpenGL 管线共存。当图形应用程序启动时,会选择其中一个。目前,默认仍是 OpenGL。只有在启动时指定使用 Metal 或者 OpenGL 初始化失败时(例如在未来不支持 OpenGL 的 macOS 版本中)才会使用 Metal。
在本 JEP 整合时,Apple 尚未移除 OpenGL。在 Apple 移除 OpenGL 之前,应用程序可以通过在 java
命令行中指定 -Dsun.java2d.metal=true
来选择使用 Metal。我们将在未来的版本中将 Metal 渲染管道设为默认选项。
在集成到 JDK 之前,我们根据 Project Lanai 对此 JEP 进行了相关工作。
测试
测试新管道的功能并不需要开发新的功能测试,因为没有改变任何 Java 2D API。现有的测试和实际应用就足够了。这些包括:
- JDK jtreg 回归测试,
- JCK 测试,
- Java 2D 和 Swing 演示,以及
- IDE,例如 Intellij IDEA 和 Netbeans,作为大规模真实世界应用程序的示例。
为了测试性能,我们使用了:
- J2DBench,包含在 JDK 中的一个 Java 2D 基准测试应用程序,
- RenderPerfTest,一个自定义压力测试,渲染多个相同基本类型的对象并测量每秒帧数 (FPS),在 Project Lanai 中开发,以及
- IntelliJ IDEA 集成开发环境性能。
最终计划的早期访问版本的性能结果在此处。
为了进一步验证新的管道,我们使用了 macOS Xcode 仪器工具来检查泄漏情况以及 Metal API 的正确使用情况。
风险与假设
-
我们在各种硬件和 macOS 版本上进行了测试,这些版本被认为具有代表性,但并非所有组合都可用。由于我们无法涵盖所有场景,因此可能存在性能限制。
-
我们对当前的 x64 二进制文件在 Apple Silicon 上进行了非常有限的(健全性)测试。目前还没有支持原生测试的 Apple Silicon 的 JDK 移植版本。
-
Metal 不支持 XOR 操作,因此我们不得不接受在这种特殊情况下性能较低的情况。很可能直到 Metal 提供对 XOR 的直接支持时,这种情况才会改变。