乘风破浪,遇见最美Windows 11之现代Windows桌面应用开发 - QT(v5.15),面向未来的3D图形抽象层RHI

2020年5月26日,Qt 5.15 LTS发布

https://www.qt.io/blog/qt-5.15-released

image

我很高兴地宣布,我们今天已经发布了Qt 5.15 LTSQt 5.15将是Qt 5系列的最后一个功能版本。因此,它有点特别,而且为Qt 6,我们的下一个主要版本做了大量的准备工作。虽然Qt 5.15对我们所有的用户都是照常支持的,但Qt 5.15也将为所有商业许可证持有者提供为期三年的长期支持,包括新的Qt for Small Business。三年支持期结束后,还可以选择延长支持。

获取Qt 5.15 LTS

作为Qt 5系列的最后一个版本,我们想确保Qt 5.15是一个伟大的版本,你可以轻松地升级到你正在进行的项目。一如既往,它与以前的Qt 5版本完全向后兼容。大量的工作用于修复错误,Qt 5.15是我们在Qt 5系列中做的最好和最稳定的版本

Qt 5.15也是迈向Qt 6的垫脚石。虽然Qt 6将在Qt的基本原理上有一些更实质性的变化,但我们正努力使代码库从Qt 5迁移到Qt 6尽可能容易。为了帮助这一过渡,我们已经将Qt 6中的许多功能标记为废弃的。在5.15中启用并修复关于已废弃功能的警告,将使你在将代码库迁移到Qt 6方面取得长足进步

但Qt 5.15也有很多自己的新功能。要了解其中的一些,请继续阅读和/或报名参加即将举行的由Tuukka Turunen和我参加的Qt 5.15 LTS网络研讨会。

image

抽象化的3D图形API

最重要的变化可能发生在图形方面。很多变化都发生在引擎盖下,我们的用户无法立即看到。在过去的一年里,我们一直在努力对我们的图形堆栈的架构进行彻底的改造。这一升级将成为Qt 6的核心,但在Qt 5.15中已经可以选择加入

我们在Qt 5中建立了图形堆栈,假设我们可以使用OpenGL作为3D图形的跨平台API。在过去的几年里,业界的重大变化使得开发和部署使用3D图形的应用程序变得更加复杂。苹果公司开始着手开发Metal,并在一段时间前放弃了对macOS和iOS的OpenGL支持Khronos组织一直在努力用Vulkan取代OpenGL,Vulkan正在向Android和Linux进军。微软的Direct 3D 12是一个完全重写的API,与旧的Direct 3D版本完全不兼容。同时,OpenGL在未来相当长的一段时间内不会消失。

由于Qt的跨平台承诺,我们希望有一个在任何地方都能使用的解决方案。为了实现这一目标,我们在一年多以前就开始为所有这些不同的API开发一个抽象层。它被称为Qt渲染硬件接口(Qt Rendering Hardware Interface)(RHI),可用于在Direct 3D、Metal和Vulkan以及OpenGL之上运行Qt Quick应用程序。它在Qt 5.15中被作为技术预览支持,你可以通过环境变量启用它来选择使用Qt RHI。在Qt 6中,该层将构成Qt架构的一个非常核心的部分。

关于RHI的更多细节,请看Laszlo关于这个主题的博文(这里这里,还有这里)。

Qt Quick 3D

Qt 5.15的另一个重要新功能也与图形有关。早在Qt 5.0时代,我们就引入了Qt Quick,作为Qt架构的一个基石。它的重点是简化动画、基于触摸的2D用户界面的创建。今天,Qt 5.15配备了完全支持的Qt Quick 3D,它将易于使用的理念扩展到将3D内容集成到基于Qt-Quick的应用程序中。通过Qt Quick 3D,你可以轻松地在QML中定义一个3D场景,定义你的网格、灯光和材料,并将一切与你的2D UI无缝结合

当你需要使用不同的技术(使用Qt 3D、Qt 3D Studio或原始OpenGL)分别开发2D和3D部分时,现在你有一个集成的解决方案,唾手可得

我们开发了一个很酷的演示,你可以用它来测试Qt Quick 3D 5.15的不同功能,比如改变灯光类型和数量、模型的复杂性和数量、纹理大小、材质、抗锯齿方法和质量等等。这样,你可以快速测试,例如,绘制的模型数量对其硬件性能的影响是否比模型中的三角形数量更大。这里有一个视频演示。

Qt Quick 3D是在Qt 5.14中作为技术预览版推出的。Qt 5.15的完全支持版本使用了许多额外的功能,如对后处理效果的支持、用于自定义几何图形的新C++ API、用于旋转的基于四元数的API以及对聚光灯的支持。由于大量的幕后工作,你现在可以更容易地在3D场景中使用2D Qt Quick,而且整体性能更高。请看Andy在Qt虚拟技术大会上的演讲,了解详情。

Qt Design Studio 1.5

Qt Quick 3D增加了大量的选项,可以制作很酷的新应用程序,在用户界面上同时包含2D和3D元素。正如你可能知道的那样,我们已经投入了大量的工作,通过Qt Design Studio向设计师提供所有这些功能。因此,我非常高兴地告诉你,Qt Quick 3D的所有功能在我们今天发布的Qt Design Studio 1.5中也得到了支持。请看关于Qt Design Studio的单独博文以了解更多细节。

Qt QML

在Qt QML中,我们专注于为Qt 6做准备,这导致了Qt 5.15中一系列有用的新特性。

QML现在有了组件的"必需(required)"属性的概念。这些是必须由组件的用户来设置的属性。组件现在可以在QML文件中被内联指定。我们还添加了一个新的、声明式的注册类型的方法

我们改进了qmllint工具,使之能更好地警告你QML代码库中可能出现的问题。我们还增加了一个新的qmlformat工具,它可以帮助你根据我们的QML编码风格指南来格式化你的QML文件

最后,我们还努力确保Qt for MCU和Qt 5.15中使用的QML是兼容的。

Qt Quick

Qt Quick中还出现了一些新功能。我们在Image元素中加入了对色彩空间的支持,并在Qt Quick Shapes中加入了一个新的PathText元素。指针处理程序有一个新的cursorShape属性,可以在桌面系统上设置鼠标指针的形状,而一个新的HeaderView项使得在TableView中添加水平或垂直标题变得容易。

其他改进

我们的桌面用户会很高兴地知道,Qt现在对客户端/自定义窗口装饰有了更好的支持。这允许你定义自己的窗口装饰,并将自定义的内容放入窗口标题栏空间

Qt Lottie是我们在Qt 5.14中作为技术预览版推出的一个模块,现在已经完全支持。该模块允许你将After Effects动画集成到你基于Qt的应用程序中。在这个网络研讨会和这篇博文中了解更多关于Qt Lottie的信息。

Qt WebEngine已经从Qt 5.14中的Chromium 77更新到Chromium 80,并带有Chromium更新中的所有新功能

Qt 3D 获得了更好的剖析和调试支持以及一些小的新特性

Qt多媒体现在支持对多个表面进行渲染。在 Qt GUI 中,图像缩放和转换例程现在是多线程的,适用于许多使用情况。

Qt Network现在支持TLS 1.3会话票和可配置的超时

在Qt Core中,QRunnable和QThreadPool现在可以与std::函数一起工作,而新的QFile::moveToTrash()方法使得以跨平台的方式将项目移动到垃圾桶中成为可能

最后,我们还增加了对Android上的本地文件对话框的支持

更多信息

image

你可以在我们上周举行的Qt虚拟技术峰会的会谈中找到很多关于Qt 5.15和Qt 6的信息。

支持期

Qt 5.15现在对我们所有的用户都可用。对于我们的开源用户,它将以与其他常规Qt版本相同的方式得到支持,直到Qt 6的发布。对于商业客户,Qt 5.15将被长期支持(LTS)三年,并在Qt 6发布后定期发布错误修复版本

请记住,Qt 5.9将在5月31日之前停止接受支持。虽然我们花了很大力气来确保Qt 5.15易于升级,但如果你需要,你仍然可以选择延长你的支持。请观看Andy Shaw在Qt虚拟技术大会上所作的内容丰富的演讲,以了解更多关于你的选择,或与我们联系,提出你的任何问题。

最后,我想感谢所有帮助使这个版本成为可能并为其做出贡献的人。

我希望你会喜欢Qt 5.15!

2019年9月16日,Qt Quick on Vulkan, Metal, and Direct3D

https://www.qt.io/blog/qt-quick-on-vulkan-metal-direct3d

现在,Qt 5.14的第一个测试版已经越来越近了,是时候开始讨论其中一个重要的新功能了。我们不可能在一篇文章中涵盖所有围绕图形堆栈改进的细节和通往Qt 6的道路,所以在第一和第二部分中,我们将描述背景并仔细看看5.14将搭载什么,然后在稍后的另一组文章中深入探讨技术细节和未来方向。

5.14的新功能页面提到。增加了第一个独立于图形API的场景图渲染器的预览,作为一个可选择的功能。这允许在Vulkan、Metal或Direct3D 11之上运行合格的Qt Quick应用程序,而不是OpenGL。

这在实践中意味着什么?

正如在Qt 6技术愿景中所概述的那样,Qt 6的主要目标之一是在Qt的大多数地方不再直接使用OpenGL,并通过适当的抽象,允许在更广泛的图形API上运行,例如,Vulkan、Metal和Direct3D。当然,OpenGL(和OpenGL ES)仍然是一种选择。这背后的主要动机不是获得性能,而是确保Qt Everywhere在未来也能保持真实,即使在OpenGL不可用或不再需要的平台和设备上。同时,当涉及到提高性能(例如,由于较少的API开销而降低CPU使用率)和在Qt Quick和其他模块(如最近发布的Qt Quick 3D)背后的渲染引擎中采用新的方式时,能够建立在现代的、较低层次的、显式的API上也能开启各种可能性。

此外,对于那些在使用Qt渲染用户界面的同时进行自己的本地2D或3D图形渲染的应用程序来说,能够用平台上主要的、支持度最高的图形API来渲染用户界面是个好消息。在这种情况下,当决定使用哪种图形API时,Qt通常不处于主导地位:例如,如果一个MacOS上的桌面应用程序希望使用Metal来渲染自己的3D内容,同时依靠Qt Quick来渲染2D UI元素,那么如果Qt Quick也通过Metal进行渲染,那就非常有利。对于那些一直关注Qt 5.x中图形演变的人来说,这听起来很熟悉:从概念上讲,这与在Qt Quick渲染器中引入对OpenGL核心配置文件上下文的支持没有什么不同--Qt Quick本身不需要也不感兴趣,但为了允许集成与核心配置文件功能相关的外部渲染代码,Qt Quick必须了解并能够处理它。因此,从这个意义上说,这个故事是我们在Qt 5中的自然延续,现在被扩展到了OpenGL以外的图形API。

所有这些现在可以引起两个明显的问题。

  • 这与Qt 5.x有什么关系?这不都是Qt 6的材料吗?
  • 你为什么不直接使用<某个图形API翻译方案的名称>,而将<API名称>标准化?

那么,Qt 5.14有什么内容?

在Qt的所有(或至少是大多数)地方对图形部分进行彻底的大修,的确是Qt 6的目标。然而,停止在5.x上的工作,并试图一次性地发明、开发和重构所有的东西,希望一切都会好起来,在实践中并不是很有吸引力。正如Qt开发者过去(现在也是)所说,任何API的第一次迭代都可能是次优的。因此,我们转而采取并列开发的方式,专注于Qt的某项UI技术。Qt Quick。

Qt 5.14预计将附带新的Qt Quick渲染路径的预览。默认情况下,它是不活跃的,因此对应用程序来说没有任何可见的变化--在内部,它们会像在早期版本中一样,直接通过基于OpenGL的代码路径。然而,那些希望尝试新方法的人可以通过设置环境变量或通过main()中的C++ API请求来选择加入。我们希望在早期获得反馈,使我们能够迭代和发展,而不必等待Qt 6.0的发布。

看一下Qt 5.14文档的快照,会发现以下内容。

image

并非所有的应用程序都能在设置了 QSG_RHI 的情况下运行。当启用基于RHI的渲染时,带有场景节点的自定义QQuickItem实现会直接调用OpenGL,或者在自定义材质中包含GLSL着色器代码,将无法运行。这同样适用于含有GLSL源代码的ShaderEffect项目。以现代方式进行自定义材质和效果的解决方案已经存在,但这些需要相应地迁移应用程序。早期采用者可以在5.14和5.15的时间框架内进行试验,但在Qt 6.0之前自然不会有广泛的采用和迁移。另一方面,许多现有的QML应用程序可能会正常工作,即使底层渲染引擎通过一个完全不同的API,如Vulkan或Metal。

为什么不是翻译层XYZ?

首先,需要说明的是,使用MoltenVK、MoltenGL、ANGLE、Zink等API和着色器翻译层的可能性仍然存在,即使并不总是开箱即用。例如,MoltenVK允许在MacOS上通过Vulkan渲染Qt Quick用户界面。如果一个Qt Quick应用程序希望只使用Vulkan,并且仍然希望在macOS上运行,那么MoltenVK就是一个选择。(只要使用适当配置的Qt构建和部署,MoltenVK在用户的系统上是可用的,等等)。

将这样一个翻译层作为一个强制性的依赖,并因此将其与Qt一起包含和部署,是一个非常不同的故事。

  • 不用说,将Qt Everywhere改为Qt Only Where External Dependencies Allow并不理想。

Qt针对的平台和环境比人们通常想象的要多得多。它只能真正依靠强制性的第三方依赖,这些依赖也能在 "异国 "环境中编译和工作,并且在出现特殊需要时容易适应。(想想INTEGRITY、QNX、定制的嵌入式Linux环境、有破损或正在开发的图形堆栈的系统、偶尔需要适应专有的碎片,或者有时必须与各种图形或组合API互操作--也许是以供应商特定的、非标准的方式--你认为早已死亡,等等。- 所有这些都需要在Qt渲染堆栈的每个层次上具有灵活性和可定制性)

  • 在运行时进行着色语言(或中间格式)之间的转换并不十分理想。Qt 6中的着色器管线预计将更多地集中在离线操作上,或者最晚在应用程序构建时进行。由于中间有一个翻译层,隐藏了现实(真正使用的是什么API,什么着色语言),这种努力在实践中很快就会变得徒劳无功,因为我们无法为真正的底层API准备,也无法输入着色器或字节码。

  • 由于目前的现实状况,所提到的一些选择是不可能的。OpenGL(ES)在可预见的未来仍然是许多设备上的主要工作对象。因此,继续直接使用单一的API只能意味着这个API是OpenGL,或者是一个可以针对OpenGL的翻译层(而且对于低性能的设备来说也足够高效)。

  • 当双方直接使用相同的API时,Qt的渲染引擎被应用程序自定义的本地渲染代码所补充的情况下,往往效果最好。在这方面,如果翻译层允许访问底层的本地对象,那么使用翻译层并不总是一个障碍(例如,当在Windows上使用Qt 5运行ANGLE时,Direct3D-Qt Quick互操作是通过EGL扩展实现的),但这并不总是到位的,当它到位时,它可能会带来另一套麻烦的处理。

  • 还有许可方面的影响和问题。想想看,Apache 2.0与GPLv2是不兼容的。在任何情况下,依靠纯商业的解决方案都是不可能的。

  • 根据经验(有些是用ANGLE,有些是用MoltenVK),使用这样的解决方案从来都不像人们最初希望的那样简单。在某些时候,保持所有选项的运行所需的努力可能会变得太大了--这种努力最好是直接用本地API来做 "正确 "的事情。其中一些翻译方案的内在平台依赖性也不是很理想--如果我们需要为Qt的每一个平台拉入另一个方案,情况很快就会变得难以维持。

因此,Qt没有走依赖低级API翻译器的路线,而是为3D图形定义了自己的高级抽象(供内部使用,暂时不暴露给应用程序)。然后由API特定的后端实现来支持,这种模式在Qt的许多组件中都很熟悉。在某些情况下,后端在本质上是特定于平台的(Metal、D3D),而在其他一些情况下,一个后端针对一个API,但有多个平台(Vulkan、OpenGL)。这由一个新的着色器管理管道补充,建立在一些第三方项目上,如glslang和SPIRV-Cross。关于这一切的更多细节将在以后的文章中出现。现在,让我们在堆栈中看得更高一些,看看在Qt 5.14中Qt Quick层面上实现了什么。

它真的有用吗?

让我们看一个例子,即来自QUIt Coding的著名的Qt5 Cinematic Experience演示应用程序。我们使用的是稍作修改的版本,其中的几个ShaderEffect项目已经更新,可以在Qt Quick场景图的两个渲染路径中发挥作用。这个版本可以在这里找到。

在设置了QSG_INFO=1的情况下,正常启动应用程序,我们会得到。

image

就像调试输出上打印的日志所显示的那样,这是在Linux桌面上的OpenGL上运行。

qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.95 ms
qt.scenegraph.general: opengl texture atlas dimensions: 2048x1024
qt.scenegraph.general: GL_VENDOR: X.Org
qt.scenegraph.general: GL_RENDERER: AMD Radeon (TM) R9 M360 (VERDE, DRM 3.23.0, 4.15.0-62-generic, LLVM 8.0.1)
qt.scenegraph.general: GL_VERSION: 4.5 (Compatibility Profile) Mesa 19.2.0-devel (git-08f1cef 2019-07-25 bionic-oibaf-ppa)
qt.scenegraph.general: GL_EXTENSIONS: ...
qt.scenegraph.general: Max Texture Size: 16384
qt.scenegraph.general: Debug context: false

如果我们设置QSG_RHI=1,情况会有什么变化?

image

qt.scenegraph.general: Using QRhi with backend OpenGL
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.95 ms
qt.rhi.general: Created OpenGL context QSurfaceFormat(version 4.5, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 0, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 1, colorSpace QSurfaceFormat::DefaultColorSpace, profile QSurfaceFormat::CompatibilityProfile)
qt.rhi.general: OpenGL VENDOR: X.Org RENDERER: AMD Radeon (TM) R9 M360 (VERDE, DRM 3.23.0, 4.15.0-62-generic, LLVM 8.0.1) VERSION: 4.5 (Compatibility Profile) Mesa 19.2.0-devel (git-08f1cef 2019-07-25 bionic-oibaf-ppa)
qt.scenegraph.general: MSAA sample count for the swapchain is 1. Alpha channel requested = no.
qt.scenegraph.general: rhi texture atlas dimensions: 2048x1024

乍一看,没有什么不同。看起来它仍然是通过OpenGL。然而,在内部,没有直接使用OpenGL,也没有GLSL着色器源在Qt Quick场景图中飞舞。相反,渲染是通过QRhi,即Qt Rendering Hardware Interface(目前是QtGui模块中的一个私有API)。

现在让我们把它变得真正有趣。让我们设置QSG_RHI_BACKEND=vulkan。

image

qt.scenegraph.general: Using QRhi with backend Vulkan
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.95 ms
WARNING: radv is not a conformant vulkan implementation, testing use only.
qt.rhi.general: Physical device 0: 'AMD RADV CAPE VERDE (LLVM 8.0.1)' 19.1.99
qt.rhi.general:   using this physical device
qt.rhi.general: queue family 0: flags=0xf count=1
qt.rhi.general: queue family 1: flags=0xe count=2
qt.rhi.general: 55 device extensions available
qt.scenegraph.general: MSAA sample count for the swapchain is 1. Alpha channel requested = no.
qt.scenegraph.general: rhi texture atlas dimensions: 2048x1024
qt.rhi.general: Creating new swapchain of 3 buffers, size 1280x720, presentation mode 2

不错。显然,它现在是通过Vulkan进行渲染。然而,即使是更奇特的Qt Quick功能,如距离场文本渲染、着色器效果和粒子,也都如期出现。

在RenderDoc中运行该应用程序,并捕捉一帧,我们得到了如下的结果。Qt Quick确实在构建Vulkan管道状态对象和命令缓冲区,而着色器代码则以SPIR-V字节码的形式提供。

image

这就是目前的情况。在本系列的第二部分,我们将看看Qt 5.14为macOS和Windows提供了什么。之后,我们将继续研究这些东西在引擎盖下是如何工作的,以及对于需要自定义材质和效果的应用程序来说会有什么影响。

激动人心的时刻即将到来!

2019年9月18日,Qt Quick on Vulkan, Metal, and Direct3D - Part 2

https://www.qt.io/blog/qt-quick-on-vulkan-metal-and-direct3d-part-2

让我们继续我们在第一篇文章中的话题。我们看到了一个在OpenGL和Vulkan之上的Linux上运行的Qt Quick应用程序的例子。我们还看到了RenderDoc中的Vulkan帧捕获,这不仅是Qt开发工作中的一个宝贵工具,而且对任何想深入了解Qt Quick如何渲染帧的人来说也是非常有用的(或者说,在应用程序的渲染问题上的故障排除)。现在,在这篇文章中,我们将重点讨论Qt 5.14为macOS和Windows提供的内容。

macOS上的Metal

令人惊讶的是,在macOS 10.13或10.14上运行qt5-cinematic-experience演示时,QSG_RHI=1(和QSG_INFO=1)的结果是。

image

qt.scenegraph.general: Using QRhi with backend Metal
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.67 ms
qt.rhi.general: Metal device: Intel(R) HD Graphics 615
qt.scenegraph.general: MSAA sample count for the swapchain is 1. Alpha channel requested = no.
qt.scenegraph.general: rhi texture atlas dimensions: 4096x2048
qt.rhi.general: got CAMetalLayer, size 2560x1440

与Qt 6的目标一致,即默认为平台的主要、最佳支持的图形API(同时仍然允许应用程序设置自己的偏好,如果他们愿意的话),在MacOS上的Qt Quick中启用基于QRhi的渲染路径,默认为使用Metal。

与基于Vulkan的渲染路径建立在对QtGui模块、QPA和一些平台插件的Vulkan实例和表面支持上类似,QRhi的金属后端依赖于在Qt 5.12前后引入的可可平台插件的金属支持。一个带有QSurface::MetalSurface的QWindow会得到一个由CAMetalLayer支持的NSView。这正是QRhi的金属后端所需要的。(这一切的工作是因为只要基于QRhi的代码路径处于活动状态,QQuickWindow就会得到适当的QSurface::SurfaceType设置)

这里的一个重要特征是能够与Qt Quick的线程渲染循环一起运行。这是非常受欢迎的,因为由于某些NSOpenGLContext和macOS 10.14中的相关API的线程问题,Qt在macOS上禁用了OpenGL的线程循环,而是默认为 "基本 "循环。这导致Qt Quick动画的流畅度有所下降。在Metal上,我们没有(根据我们目前的知识)任何关于线程设置的问题,所以我们可以再次默认为线程渲染循环。(渲染循环的默认选择可以通过设置QSG_RENDER_LOOP环境变量来覆盖;这个变量在与QSG_RHI结合时也被支持)。

我们提到RenderDoc是一个调试Qt应用程序在OpenGL、Vulkan或Direct3D上运行时的帧渲染的工具。对于金属,可以使用XCode及其内置的GPU帧捕获。

image

在XCode中快速打开Qt项目准备调试的一个有用方法是在终端运行make xcodeproj && open *.xcodeproj (如果qmake还没有运行,则运行qmake -spec macx-xcode)。点击Cmd-R就可以启动调试器了。在Qt开发过程中,我们也经常使用这个方法。如果Metal的GPU捕获不可用,即使Qt Quick被设置为通过Metal渲染,检查Product -> Scheme -> Edit scheme...,并将GPU Frame Capture改为Metal。

image

在XCode中运行调试构建的应用程序将启用金属验证,这意味着当以某种不正确的方式使用金属API时,XCode将抛出一个(希望是)有用的警告并中断程序的执行。与其他平台不同的是,在不通过XCode进行调试的情况下,不能启用Metal API验证。(所以与Vulkan和D3D不同,设置QSG_RHI_DEBUG_LAYER不会有任何影响)

iOS上的金属

那iOS或tvOS呢?

嗯,在写这篇文章的时候,平台插件中与金属有关的管道还没有,这也意味着QRhi的金属后端还没有在这些平台上进行测试。这就是为什么Qt 5.14的新功能页面只在Qt Quick部分提到了macOS。预计在不远的将来,也许在5.15版本中会增加支持。

macOS上的Vulkan

那么通过MoltenVK的Vulkan呢?

正如第一部分中提到的,通过Vulkan请求渲染,然后依靠MoltenVK在运行时将API调用和SPIR-V着色器翻译成金属和金属着色语言也是一种选择。这需要一个支持Vulkan的Qt构建,这在苹果平台上不是开箱即用的。详情请看这篇文章,关键是要通过-I来配置,并确保在运行时可以通过设置QT_VULKAN_LIB来找到这些库。

需要注意的是,这种方法只是在尽力而为的基础上被支持。在苹果平台上渲染的主要支持方式是通过Metal。

在QSG_RHI_BACKEND=vulkan的情况下运行演示程序(使用适当配置的Qt 5.14版本),我们可以得到。

image

qt.scenegraph.general: Using QRhi with backend Vulkan
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.67 ms
qt.rhi.general: Physical device 0: 'Intel(R) UHD Graphics 630' 0.2.1835 (api 1.0.92 vendor 0x8086 device 0x3E9B type 1)
qt.rhi.general: using this physical device
qt.rhi.general: queue family 0: flags=0x7 count=1
qt.rhi.general: 17 device extensions available
qt.scenegraph.general: MSAA sample count for the swapchain is 1. Alpha channel requested = no.
qt.scenegraph.general: rhi texture atlas dimensions: 2048x1024
qt.rhi.general: Creating new swapchain of 2 buffers, size 1280x720, presentation mode 2

值得注意的是,我在macOS 10.13上运行时遇到了问题,在使用线程渲染循环时出现了锁定和崩溃。升级到较新的(1.0.121)Vulkan SDK(包括MoltenVK)导致了一系列新的问题,无法启动应用程序。(我一直得到类似于https://github.com/KhronosGroup/MoltenVK/issues/695),有待以后调查。在这里,在装有10.14和半新的Vulkan SDK/MoltenVK的Mac Mini上,结果是相当好的,正如截图上所见证的。

Windows

Windows是我们有最多选择的平台。在4个主要的QRhi后端(Vulkan、Metal、D3D11、OpenGL)中,在Windows上可以使用不少于3个。Direct3D 11、Vulkan和OpenGL。

这就引出了一个明显的问题。为什么只有3个?不应该是4个,而Direct3D 12是第四个吗?

目前还没有D3D12的后端。这可能会在以后发生变化,因为这在计划中,但目前没有安排。当我们谈到这个话题时,值得注意的是,在Qt 5.8中为Qt Quick添加的实验性的直接到D3D12的后端现在已经在架构上被废弃了(因为我们以一种全新的方式来解决多个图形API的问题),并将在Qt 6中被移除。

在Windows上,当设置QSG_RHI=1时,默认是Direct3D 11。像往常一样,如果需要Vulkan或OpenGL,可以用QSG_RHI_BACKEND来覆盖。

image

qt.scenegraph.general: Using QRhi with backend D3D11
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.67 ms
qt.rhi.general: DXGI 1.2 = true, FLIP_DISCARD swapchain supported = true
qt.rhi.general: Adapter 0: 'NVIDIA GeForce RTX 2060' (flags 0x0)
qt.rhi.general: using this adapter
qt.rhi.general: Adapter 1: 'Microsoft Basic Render Driver' (flags 0x2)
qt.scenegraph.general: MSAA sample count for the swapchain is 1
qt.scenegraph.general: rhi texture atlas dimensions: 2048x1024

值得注意的是,我们需要Direct3D 11.1,而不是11.0。这主要是因为我们需要VSSetConstantBuffers1
(以及相关的PS和CS的变体)。这应该不是问题,除非有人想在没有平台更新的普通Windows 7上运行。说到Windows 7,需要注意的是,从Qt 5.14开始,基于D3D11的渲染目前在Windows 7上不能正常运行,因此在5.14的新特性页面上只提到了Windows 10。这是以后要补救的事情(但前提是Windows 7要继续成为Qt 6的支持平台)。

要启用Direct3D调试层,请将环境变量QSG_RHI_DEBUG_LAYER设置为1。这对Vulkan也适用,只要验证层可用(例如来自已安装的Vulkan SDK)。Qt很方便地将这些信息引导到调试输出(就像它们通过qDebug输出一样)。

Vulkan和OpenGL在Windows上应该可以正常工作,所以我将避免通过添加更多的屏幕截图来使文章变长。

与Vulkan和Metal一样,QRhi的OpenGL后端建立在一些(但不是全部)现有的OpenGL使能器和平台管道上,例如,QOpenGLContext、QOpenGLFunctions,以及windows平台插件(WGL、EGL)的底层管道。因此,适用于直接在OpenGL上运行的Qt Quick应用程序的一切,在这里也适用。(桌面与ANGLE与软件,环境变量如QT_OPENGL)

说到ANGLE,人们期望它能在Qt 6中作为一个直接的依赖关系被移除。这需要进一步调查,以确保我们不会失去对特殊用例的支持,但目前的计划是,拥有基于QRhi的渲染路径,并支持Direct3D 11、OpenGL(通过WGL)和Vulkan,这对Windows上的Qt 6应用程序来说已经足够了。

本篇文章到此结束。在第三部分,我们将最终开始深入研究QRhi是什么,以及如何处理着色器。

2019年9月24日,Qt Quick on Vulkan, Metal, and Direct3D - Part 3

https://www.qt.io/blog/qt-quick-on-vulkan-metal-and-direct3d-part-3

在我们关于Qt图形系列的第三部分(第一部分,第二部分)中,我们将看看在Qt 5.14中,当把场景图切换到通过QRhi(Qt渲染硬件接口)进行渲染时,Qt Quick是如何处理着色器的。我们选择在深入研究RHI本身之前介绍着色器处理,因为使用ShaderEffect项目或自定义材质的Qt Quick应用程序必须自己提供片段和/或顶点着色器代码,因此它们需要了解(并在Qt 6之前迁移到)着色器处理的新方法。

谈到Qt 6:虽然这里描述的一切都适用于,而且只适用于Qt 5.14,并可能在以后的版本中发生变化,但一旦剩下的一些粗糙的边缘被消除,我们在这里所做的可能会形成Qt 6中图形和计算着色器处理的基础。

为什么是新的东西?

问题一。

查看qtdeclarative源码树(即包含QtQml、QtQuick和相关模块的git repo),并深入到包含Qt Quick场景图内置材质的顶点和片段着色器的着色器目录,发现Qt Quick已经包含每个GLSL顶点或片段着色器的两个版本。

image

为什么?这是由于支持核心配置文件的OpenGL上下文(适用于3.2及以上版本)。由于OpenGL实现不需要支持在这样的上下文中编译GLSL 100/110/120着色器,Qt别无选择,只能使用两个变体:一个适用于OpenGL ES 2.0、OpenGL 2.1和兼容性配置文件,另一个(实际是150版本)只在上下文变成核心配置文件时使用。正如本博客系列的第一部分所描述的那样,这一点至关重要,可以让应用开发者决定,当他们的应用结合了自己的定制OpenGL渲染和基于Qt Quick的用户界面时,应该请求什么样的OpenGL上下文;无论上下文是兼容性还是核心配置文件,Qt Quick都可以进行渲染。

如果现在我们需要兼容Vulkan的GLSL、HLSL和MSL,那该怎么办?那么,不幸的是,这种方法并没有真正的扩展。

问题二。

一些较新的图形API已经没有内置的着色器编译支持了,与OpenGL不同。(good bye glCompileShader)而且即使它们有,至少作为一个单独的库,它们可能在运行时不提供反射功能,这意味着没有办法动态地发现顶点输入和其他着色器资源,一个顶点、片段或计算着色器期望什么,以及这些资源的布局是什么。(例如,统一块中的成员的名称和偏移量是什么?)

问题3.

一个内部细节:Qt Quick scenegraph的批处理系统依赖于重写顶点着色器,对于使用所谓的合并批处理的材料(当多个几何节点最终产生一个单一的绘制调用时,我们会得到这样的结果)。在将着色器传递给glCompileShader之前临时重写着色器,在只使用一种着色语言的情况下是合适的,但当我们必须为多种不同的语言实现相同的逻辑时,就不适用了。

那是什么?

看看Khronos SPIR的网页,里面有一张关于SPIR-V开源生态系统的漂亮的信息图片。为什么不尝试在此基础上建立呢?

我们感兴趣的关键组件是

  • glslang,一个从(OpenGL或Vulkan风格)GLSL到SPIR-V的编译器,一个中间表示。
  • SPIRV-Cross,一个用于对SPIR-V进行反射并将其分解为高级语言的库,例如GLSL、HLSL和MSL。

因此,如果我们 "标准化 "一种语言,比如Vulkan风格的GLSL,将其编译为SPIR-V,我们就有了适合Vulkan的东西。如果我们通过SPIRV-Cross运行SPIR-V二进制文件,我们就可以得到我们需要的反射信息,并且可以为各种GLSL版本、HLSL和金属着色语言生成源代码。

(是的,GLSL仍然是必不可少的,因为虽然有OpenGL的扩展来消费SPIR-V,但指望它在实践中是行不通的,因为这样的扩展很可能在90%的Qt的目标平台和设备上缺失--例如,OpenGL ES 2.0仍然是一个东西,即使是在2019年)

最后,将这一切(包括反射元数据)打包成一个容易(去)序列化的包,这就是我们的解决方案。

因此,在运行设置了QSG_RHI=1的Qt Quick应用程序时,目前利用的管道是。

Vulkan-flavor GLSL

[ -> generate batching-friendly variant for vertex shaders]

-> glslang : SPIR-V bytecode

-> SPIRV-Cross : reflection metadata + GLSL/HLSL/MSL source

-> pack it all together and serialize to a .qsb file

.qsb扩展名来自于执行上述步骤的命令行工具的名称--qsb,即Qt Shader Baker的缩写。(不要与qbs相混淆)

在运行时,.qsb文件被反序列化为QShader实例。这是一个相当简单的容器,遵循标准的Qt模式,如隐式共享,并承载一个着色器的源码和字节码的多个变体,以及一个QShaderDescription,不出所料,它包含反射数据。和RHI的其他部分一样,这些类暂时是私有API。

图形层直接消耗QShader实例。图形管道状态对象为每个活动着色器阶段指定一个QShader。然后QRhi后端从QShader包中挑选合适的着色器变体。

从Qt 5.14开始,这在实践中意味着要寻找

  • 针对Vulkan的SPIR-V 1.0。
  • 当以D3D11为目标时,HLSL源代码或DXBC for Shader Model 5.0。
  • 当以Metal为目标时,寻找与Metal 1.2兼容的MSL源代码或预编译的metallib。
  • 当针对OpenGL ES上下文时,320 es, 310 es, 300 es, 100 es中的一个版本的GLSL源(按照优先级顺序,从上下文支持的最高版本开始)。
  • 460, 450, ..., 330, 150版本的GLSL源,当针对OpenGL core profile上下文时(按优先级顺序,从上下文支持的最高版本开始),和
  • 当以非核心OpenGL上下文为目标时,版本120、110中的一个的GLSL源(按照该优先级顺序)。

上面列表中的HLSL和MSL条目一开始可能看起来有点奇怪。这是因为虽然我们可以在运行时从源码编译HLSL和MSL(我们的默认方法),但已经做了一些实验,允许在.qsb包中包含预编译的中间格式。在实践中,这意味着在上述管道中的 "打包 "步骤之前调用fxc(还没有dxc支持--它也在计划中,但只有当我们开始关注D3D12时才会真正相关)或Metal命令行工具。当然,这里的挑战是,这些工具与他们的平台(分别是Windows和macOS)相联系,所以qsb只能在该平台上运行时调用它们。因此,当在Linux上手动生成一个.qsb文件时,例如,这不是一个选项。从长远来看,这可能不是一个问题,因为在Qt 6的时间框架内,我们将需要研究更好的构建系统集成,所以手动运行像qsb这样的工具将不太常见。

等等,这个qsb的东西是怎么来的?

来自Qt Shader Tools模块。它提供了一个API,QShaderBaker,和一个命令行主机工具,qsb,来执行上述的编译、翻译和打包步骤。

只有一个问题:这暂时是一个qt-labs模块,所以它并不随Qt 5.14一起发货。

这是为什么呢?嗯,主要是因为第三方的依赖性,比如glslang和SPIRV-Cross。当涉及到能够在我们所有的目标平台上编译和运行时,有许多事情需要调查和弄清楚,有些事情与许可证有关,等等。如果这一切听起来很熟悉,那是因为其中一些问题在本博客系列的第一部分中被提及,当时我们谈到了API翻译解决方案。所以现在生成一个.qsb包包括检查和构建这个模块,然后手动运行qsb工具。

虽然我们需要一个属于Qt的解决方案,依靠离线着色器处理并不是一件坏事。在任何情况下,这都是我们在Qt 6中的目标之一。我们的愿景是要有一个能与Qt的构建系统集成的东西,这样上述的着色器处理步骤就能在应用程序(或库)构建时完成。然而,这被留作未来的工作,主要是因为即将到来的qmake->cmake过渡。一旦事情稳定下来,我们就可以开始在新系统的基础上建立一个解决方案。

那么,Qt Quick在Qt 5.14中是如何做到的呢?

看看qtdeclarative/src/quick/scenegraph/shaders_ng,答案是显而易见的:通过手动运行qsb(注意命名恰当的compile.bat),并通过Qt资源系统将生成的.qsb文件纳入Qt Quick库中。如上所述,这在以后会变得更加复杂,但现在已经完成了工作。

image

.vert和.frag文件包含与Vulkan兼容的GLSL代码,并且不在Qt Quick构建中运输。只有.qsb文件被列在scenegraph.qrc中。

这个过程在这张从我的NDC TechTown 2019演讲中借用的幻灯片中得到了很好的总结。

image

每个材质只有一对顶点和碎片着色器,总是写成与Vulkan兼容的GLSL,遵循一些简单的约定(比如只使用一个统一的缓冲区,放置在绑定0处)。

然后,这些文件都会通过着色器烘焙机制运行,从而形成一个QShader包。在这个例子中,结果是同一着色器的6个版本,加上反射数据(qsb可以打印成JSON文本;但是.qsb文件本身是压缩的二进制文件,人类无法阅读)。上面的问题1和2就这样解决了。

注意着色器列表中的[Standard]标签。如果这是一个顶点着色器,并且还指定了-b参数,那么输出着色器的数量将是12个,而不是6个。另外6个着色器会被标记为[Batchable],表明这些着色器是对批处理友好的,针对Qt Quick scenegraph的渲染器稍作修改的变体。这就解决了问题3,但代价是存储需求略高。(但由于减少了运行时间的工作,这最终可能是值得的)

这涵盖了新的着色器管道背后的核心概念。我们将在另一篇文章中讨论ShaderEffect和QSGMaterial。基本的想法(从Qt 5.14开始)是传递.qsb文件名而不是着色器源字符串,但是材质尤其需要注意更多的东西(主要是由于使用统一的缓冲区而不是单一的制服,以及由于没有任何人可以任意改变状态的每线程当前上下文的概念)。所以关于这一切,下次再谈。

2021年2月9日,针对其他Qt版本构建Qt WebEngine

https://www.qt.io/blog/building-qt-webengine-against-other-qt-versions

image

我们最近收到了很多关于如何构建和测试Qt WebEngine 5.15.3的问题,所以我想在这里提供混合版本构建的细节和潜在问题。

这也适用于任何在Qt 5.12.x下构建WebEngine 5.15.x的人,这是我们提供的另一种混合版本的支持。

首先确保你有所有的构建依赖,Linux的依赖被列在从Git构建Qt 5。对于 macOS 和 Windows,这主要意味着要确保有 Python2(是的,2,Chromium 还没有完全迁移到 Python3)和新的 Qt 5.15.3,一个 node.js 二进制文件,它现在被 Chromium 用来打包某些网页界面,可以从 nodejs.org 下载或在 macOS 上使用 Homebrew。还需要Bison和flex,但在Mac和Linux上应该是相当标准的,在Windows的qt5/gnuwin32中。

最简单的构建方式是和Qt WebEngine的开发者一样,作为完整的Qt源码构建的一部分。你从qt5.git检出所有的Qt,检出5.15.2并进行git子模块更新--递归,然后进入qtwebengine模块目录,在那里检出5.15(或5.15.3一旦分支)并在qtwebengine目录下进行另一次git子模块更新以获得正确的src/rdparty版本。然后你就可以从 qt5 根目录下正常地配置和构建所有的 Qt 了(参见再次从 Git 构建 Qt 5)。

如果你已经安装了Qt5,只是想构建Qt WebEngine,你同样需要qtwebengine的git源代码(直到5.15.3源代码包被发布),如上所述签出5.15分支,然后从你安装的Qt对qtwebengine的源代码目录运行qmake。你可以在qmake命令行中的 -- 后面添加任何配置选项,比如说。

qmake ../qtwebengine -- -enable-webengine-proprietary-codecs -system-webengine-icu

一旦配置好,你就可以像往常一样用make、nmake或jom进行构建和安装。但是请注意,构建过程将启动一个嵌套的ninja构建系统,你可以在配置前用环境变量NINJAFLAGS覆盖ninja标志,或者在配置后用NINJAJOBS附加到它们。例如,如果你使用icecc,或者你的机器没有足够的内存来运行默认数量的ninja线程和通常非常耗费内存的chromium源(每个线程2-3Gbyte),这就很有用。

这就是你需要做的,只要你使用qmake,或任何使用pkg-config查找Qt WebEngine的构建系统,但需要注意的是,如果你需要在cmake项目中使用新构建的Qt WebEngine,那么qt5构建系统为这种混合版本的情况生成的cmake文件会有一点错误。例如,生成的Qt5WebEngineCoreConfig.cmake将包含这样的代码。

find_package(Qt5${_module_dep}
    5.15.3 ${_Qt5WebEngineCore_FIND_VERSION_EXACT}
    ${_Qt5WebEngineCore_DEPENDENCIES_FIND_QUIET}
    ${_Qt5WebEngineCore_FIND_DEPENDENCIES_REQUIRED}
    PATHS "${CMAKE_CURRENT_LIST_DIR}/.." NO_DEFAULT_PATH
)

这将使cmake寻找5.15.3或更新版本的Qt依赖,当然,如果你针对5.15.2构建,则不存在这种依赖。你需要为三个WebEngine模块分别修改生成的cmake文件,以寻找5.15.2或只寻找5.15。但最简单的,如果你不介意误导性的SO数字,就是在qtwebengine源中编辑.qmake.conf,并将MODULE_VERSION改为5.15.2,或任何你正在构建的Qt版本。

注意Qt WebEngine 5.15.3对于一个点发布版本来说是一个异常大的更新。底层的Chromium版本已经更新到了87版本,因为它是Qt 5.16版本,这次更新有两个目的:a) 尽可能地保持版本差异,因为我们从现在开始只向5.15版本回传安全补丁;b) 支持在macOS Rosetta2上运行,不幸的是,它没有足够好的x64模拟来运行Chromium而不作修改。 这也意味着我们在发布前比以往更重视测试。

2020年3月27日,Qt 5.15中新的QML语言功能

https://www.qt.io/blog/new-qml-language-features-in-qt-5.15

image

虽然Qt 6.0的大变化正在进行中,但QML在5.15中已经有了一些新的语言特性。请继续阅读,以了解所需的属性、内联组件和nullish coalescing。

必需属性(Required Properties)

有时,你有一些需要设置某些属性的组件,但并没有真正的好的默认值。例如,你可能关心你的按钮的可访问性,所以你创建了一个 AccessibleButton,它应该总是有一个描述。

// AccessibleButton.qml
Button {
    property string description
    Accessible.description: description
}

然而,按钮有一个描述属性的事实,并不意味着任何人会设置它。因此,你或你的同事可能会在某个时候将该组件实例化为。

AccessibleButton {
    onClicked: (mouse)  => { /* fancy business logic here */ }
}

这么多的可访问性。描述现在只是一个空字符串!你当然可以给属性一个默认值,但哪一个呢?当然,你可以给这个属性一个默认值,但哪一个?"按钮"?几乎没有帮助。"你不应该听到这个"?好吧,至少QA现在可能会抓住它。但如果QML引擎知道这个属性需要被设置,那不是更有用吗?

在Qt 5.15之前,不幸的是,没有办法强制要求描述被设置。但从Qt 5.15开始,这将成为可能。

Button {
    required property string description
    Accessible.description: description
}

现在,如果创建了一个AccessibleButton,但没有设置描述,整个应用程序将无法启动。然而,如果该组件是动态创建的,例如通过加载器,就不能这样做。在这种情况下,只会有一个运行时警告。

我们还计划为qmllint和QtCreator添加进一步的工具支持,在所需的属性没有设置时显示警告。

必需属性和委托

此外,必要属性在委托中扮演着特殊的角色。正如你可能知道的,委托可以通过名字直接访问所提供的模型的模型角色,以及一些进一步的属性,如模型和索引。

ListView {
    model: root.myModel
    delegate: Text {
        id: delegate
        color: index % 2 ? "gray" : "black"
        text: description
    }
}

如果你的委托人不包含必需的属性,这里没有任何变化。但是,如果它们至少包含一个必需的属性,这些名字就不能再被访问了。相反,你必须通过将它们指定为必填属性来明确选择。

ListView {
    model: root.myModel
    delegate: Text {
        id: delegate
        required property int index
        required property string description
        color: index % 2 ? "gray" : "black"
        text: description
    }
}

然后,QML引擎将相应地设置所需的属性。请注意,在你的模型是可编辑的情况下,新方法和旧方法之间有一个显著的区别。在旧的方法中,你可以写

Text {
    id: delegate
    Component.onCompleted: description = "My fancy new text"
}

而模型也会相应地被更新。但是,如果你做

Text {
    id: delegate
    required property string description
    Component.onCompleted: delegate.description = "My fancy new text"
}

那么与描述的绑定就会被破坏(QML引擎会打印一个警告),模型也不会被更新。我们决定采用这种行为,以确保组件在委托中使用和在委托之外使用时不会有太大的区别。此外,我们不希望鼓励任何人对属性进行强制性的赋值(因为这破坏了一般的绑定)。

如果你想实际更新模型的值,当然还有一种方法可以实现。让model成为一个必需的属性,然后写

Component.onCompleted: model.description= "My fancy new text"

我们建议你总是在委托中使用必要的属性。这可以避免不合格的查找,这对工具来说是有问题的,而且往往比较慢。

内联组件

5.15的另一个新功能是内联组件。顾名思义,它们允许你在一个文件中定义一个新的组件。其基本语法是

component <component name> : BaseType {
    // declare properties and bindings here
}

在这个文件中,你可以用它的名字来引用新的组件,就像它被定义在自己的文件中一样。让我们以LabeledImage组件为例来说明其工作原理。

// Images.qml
import QtQuick 2.15

Item {
    component LabeledImage: Column {
        property alias source: image.source
        property alias caption: text.text

        Image {
            id: image
            width: 50
            height: 50
        }
        Text {
            id: text
            font.bold: true
        }
    }

    Row {
        LabeledImage {
            id: before
            source: "before.png"
            caption: "Before"
        }
        LabeledImage {
            id: after
            source: "after.png"
            caption: "After"
        }
    }
    property LabeledImage selectedImage: before
}

也可以在其他文件中引用该组件。在这种情况下,你需要在它的名字前加上包含组件的名字。

// LabeledImageBox.qml
import QtQuick 2.15

Rectangle {
    property alias caption: image.caption
    property alias source: image.source
    border.width: 2
    border.color: "black"
    Images.LabeledImage {
        id: image
    }
}

在这一点上,你可能会想,既然QML已经有了Component类型,为什么我们还需要inline components?看看前面的例子,我们可以看到,内联组件允许你做以下Component所不能做的事情。

  • 你可以创建一个组件的实例,而不需要使用Loader的费用。
  • 你可以在属性声明中使用组件的类型。
  • 你可以在其他文件中引用该组件,而不是在它所定义的文件中引用。

我们希望你能像我们一样发现内联组件的便利性。

空白凝聚(Nullish Coalescing)

最后一个新的语言功能是由我们的实习生Maximilian Goldstein实现的。虽然QML通常只支持EcmaScript 6,但Max增加了对一个即将到来的语言功能的支持,该功能目前正在被添加到最新的EcmaScript标准中:nullish coalescing。引用MDN的话。

nullish凝聚运算符(??)是一个逻辑运算符,当其左侧的操作数为空或未定义时,返回其右侧的操作数,否则返回其左侧的操作数。

详情见MDN页面。这里有一个例子,它可以在QML中用来设置JSON中的属性,并在没有提供这些属性的情况下提供合理的默认值。

Item {
    property var settings
    property int brightness: settings.brightness ?? 100
    property color color: settings.color ?? "blue"
    Component.onCompleted: settings = JSON.parse(settingsString)
}

注意,我们不能用||代替??来表示亮度,因为settings.brightness可能是0,在这种情况下,我们就会得到默认值。

展望未来

随着Qt 6的到来,更多的变化必然会在QML中出现。除了修改QML引擎的内部结构,我们希望利用静态类型来生成更快的代码(包括编译成C++),并改进我们的工具。此外,当我们专注于6.0版本的大型主题时,我们对小型的生活质量改进保持开放的心态:可选的链或增加对fetch API的支持只是社区功能请求的两个例子,我们会考虑在更大的6.x时间表中(尽管不是最初的6.0版本)。你有一个你想在QML中看到的功能吗?欢迎发表评论,或者更好的是,在我们的bugtracker中创建一个建议。未来是用Qt来写的!

QT开发工具(官方清单)

https://doc.qt.io/tools.html

Qt工具在所有支持的开发平台上运行,促进了应用程序的设计、开发、测试和部署。

Qt Creator

https://doc.qt.io/qtcreator/

一个跨平台、完整的集成开发环境(IDE),用于开发针对桌面、嵌入式和移动平台的应用程序。

Qt Design Studio

https://doc.qt.io/qtdesignstudio/

一个UI设计和开发环境,用于创建动画UI。

Qt 3D Studio

https://doc.qt.io/qt3dstudio/

一个用于创建交互式三维演示、UI和应用程序的合成工具。

扩展Qt Creator

https://doc.qt.io/qtcreator-extending/

一本记录了Qt Creator的各种功能扩展方式的手册。

Qt Designer

https://doc.qt.io/qt/qtdesigner-manual.html

用Qt Widgets设计和构建图形用户界面的工具。

Qt语言学家(Linguist)

https://doc.qt.io/qt/qtlinguist-index.html

用于将Qt C++ 和Qt Quick应用程序翻译成当地语言的工具。

Qt助手(Assistant)

https://doc.qt.io/qt/qtassistant-index.html

一个用于查看Qt帮助文件格式的文档的工具。

Qt VS 工具

https://doc.qt.io/qtvstools/

将Qt开发工具集成到Microsoft Visual Studio中。

伽马射线(GammaRay)

https://doc.qt.io/GammaRay/

一个用于在运行时观察和操作Qt应用程序的自省工具。

QML Live

https://doc.qt.io/QMLLive/

一个本地和远程的Qt Quick 实时重载系统。

Qt Installer Framework

https://doc.qt.io/qtinstallerframework/

一套用于创建桌面平台安装程序的工具和实用程序。

构建工具: CMake

https://doc.qt.io/qt/cmake-manual.html

在Qt中使用CMake构建工具的文档。

构建工具: qmake

https://doc.qt.io/qt/qmake-manual.html

qmake 编译工具的文档。

构建工具: Qbs

https://doc.qt.io/qbs/

Qbs 编译工具的文档。

QDoc手册

https://doc.qt.io/qt/qdoc-index.html

文档构建工具的用户手册。

QT质量工具(官方清单)

https://doc.qt.io/tools.html

GUI测试自动化和代码覆盖工具。

Squish

https://doc.froglogic.com/squish/latest/

一个专业的自动化GUI测试框架。Squish使得测试基于各种工具包的GUI应用程序成为可能,包括Qt。

Coco

https://doc.froglogic.com/squish-coco/latest/

一个用于C/C++、C#和QML的代码覆盖工具链。

Test Center

https://doc.froglogic.com/squish-testcenter/latest/

一个结果服务器,提供了一个集中的地方来存储所有的测试结果。

QT开发工具(民间清单)

主要工具

  • Qt Designer — 所见即所得的界面设计工具, 可以用拖拽的方式将控件排布在界面上,支持layout, 支持signal/slot编辑。 生成的文件保存为ui格式, ui是xml格式的普通文本文件, 默认编码为utf8, 所以界面上还可以直接写中文(但是不推荐这么做哦,还是应该用标准的Qt国际化的方法来翻译界面。).

  • Qt Assistant — 类似MSDN的文档查看工具, 支持html的子集(图片、超链、文本着色), 支持目录结构、关键字索引和全文搜索, 可以很方便的查找Qt的API帮助文档,所以是编程必备、使用率最高的工具。

  • qmake – 用于生成Makefile(编译的规则和命令行)的命令行工具。 它是Qt跨平台编译系统的基础。 它的主要特点是可以读取Qt本身的配置, 为程序生成与库一致的Makefile。

  • Qt Linguist — 被称为Qt语言家的Linguist是用于界面国际化的重要工具, 但其实它并不能帮你翻译,它的主要任务只是读取翻译文件、为翻译人员提供友好的翻译界面。 听起来这个功能好像不太够, 没错! Linguist必须要和其他工具一起用才能完成Qt国际化。 关于国际化可以参考bug写的Qt国际化和本地化。 另外,大家可能还不知道, Linguist工具从4.5开始可以支持Gettext的PO文件格式了哦~

  • tmake – 和qmake功能一致,是qmake的前身。从Qt3开始tmake全面被qmake替代。

  • qtdemo – Qt例子和演示程序的加载器, 也可以看作是Qt提供的一个有用的工具。 有了这个工具, 用户可以很方便的查看Qt提供的多姿多彩的例子程序,从中选择自己需要的, 不仅可以看到程序运行的情况,还可以查看源码和文档。

次要工具

  • lupdate – Qt国际化的重要命令行工具之一,它的功能是从源码文件或其他资源文件中提取需要翻译的字符串,并将之用正确的编码和格式存入ts文件中。 这个ts文件是xml格式的普通文本文件,但不建议用普通的文本编辑工具来编辑,最好的方法是用Linguist来处理这个文件。

  • lrelease – Qt国际化的重要命令行工具之一, 它负责将ts文件转化为程序使用的qm文件。转化过程最大的变化是去掉了原始文件中所有的空白和未翻译的内容, 并将存储格式压缩, 所以qm文件是保留所有有效信息但占用硬盘最少的格式。

  • uic – UI Compiler, 顾名思义,这个命令行工具是用来编译ui文件的,它能把ui文件转化为编译器可以识别的标准C++文件,生成的文件是一个.h。 这个工具通常情况下不需要用户去手动调用, qmake会帮你管理ui文件和调用uic工具。 具体的可以参考笔者的另外一篇帖子 Qt4中ui文件的使用方法。

  • moc – Meta Object Compiler, 直译过来是元对象编译器,简单的说这是个预编译工具,用来生成一些与信号和槽相关的底层代码。 该工具处理带有Q_OBJECT宏的头文件, 生成形如moc_xxx.h, moc_xxx.cpp的C++代码,之后再与程序的代码一同编译。 同样,这个命令行工具也不需要用户手动调用, qmake会在适当的时候调用这个工具的。

三级工具

  • rcc – Resource Compiler资源文件编译工具。 Qt的资源系统是自己一套特别的设计, 工程中可以包含后缀为qrc的资源文件, 由rcc工具根据qrc的内容将相关的文件编译为二进制,并与源码编译在一起,保存在应用程序的二进制文件中。 这个命令行工具同样不需要手动调用,由qmake调用。

  • qconfig – QtEmbedded feature配置工具。 众所周知,嵌入式版本的Qt可以自己定义一个feature定义文件叫qconfig-xxx.h,里面定义一些预定义的宏, 通过这个文件可以在编译阶段去掉一些feature, 以减少Qt库的footprint。 这个qconfig工具就是用来编辑feature定义文件的。 具体的参考笔者的帖子简单Qt裁剪。

  • qt3to4 – 用于Qt3程序升级为Qt4程序的移植工具。 它的原理是根据xml文件里定义的一系列文本替换的规则去做文本替换, 所以…怎么说呢,这个工具的功能比较有限, 不可避免的需要很多人工干预才能解决编译和运行的错误。 故而笔者的建议还是重头写程序比较靠谱。

  • qvfb – 一般做嵌入式开发的用户对这个工具应该不陌生。 这是个有几分神奇色彩的模拟器, 它可以模拟framebuffer设备(尺寸、色深),还可以通过skin文件模拟硬件键盘的布局(包括特殊键值的按键), 是在x86环境下调试嵌入式程序必不可少的有效工具。 无怪乎minigui也比较无耻的偷窃了这个工具…实在是诱惑力太大了

四级工具

  • qtconfig – X11系统下用于配置Qt环境的工具。 可以设定字体、Style、Palette、打印机等。 设定信息会保存在用户家目录,所以可以按不同用户的喜好来设定不同的值。

  • qcop – 嵌入式环境qtopia带的进程间通讯的工具, 用于进程间的通讯和进程间API的相互调用。

  • pixeltool – 类似放大镜的工具,可以看清鼠标滑过的每个像素。

  • findtr – 从源码提出翻译字串,保存为Linux的po格式。 po是Linux系统下国际化方法gettext使用的标准格式, 所以这个工具是为了和Linux本身的国际化方法兼容而提供的。

  • uic3 – Qt4中提供的处理Qt3 ui文件的工具,生成的代码是Qt4的代码,可以放在Qt4的工程里使用。 值得注意的是,uic3生成的代码有一部分会使用Qt3Support库的API, 不是纯的Qt4代码。

  • phonesim – Qtopia里带的奇妙工具, 用于调试手机环境。 可以模拟提供AT命令接口的modem设备。 有了这个工具就可以在桌面环境下调试应用和modem之间的交互逻辑, 简单的说Qtopia里像接打电话、收发短信、STK程序等功能都是靠这个工具来调试的。

  • makeqpf – Qt为了嵌入式环境的需要自创了一种字体格式叫qpf, 这个格式是个位图字体, 它把已经预渲染的文字直接保存成二进制内容, 使用的时候可以用内存映射加载, 从加载到绘制的过程不需要计算,所以速度非常快。 makeqpf工具就是用来创建qpf格式的字体的,它可以读取系统中的字体格式, 根据用户的设定生成特定字号规格的qpf文件供用户使用。

其他工具

  • lconvert – 4.5版本新引入的工具, 用于翻译文件之间的格式转换, 将ts格式转换为其他工具可读取的XLIFF格式。

  • qdbusxml2cpp – QtDBus XML编译器, 用于将xml格式的DBus远程调用的对象和函数API的描述文件翻译为C++代码。 这个工具创建的是个代码的框架,里面的API具体实现要用户自己来填充。

  • D-Bus Viewer — 可以用来查看D-Bus对象及其对外提供的API, 可以通过双击API的方式调用某个方法, 还可以注册信号, 这样所有发出的信号都会显示在窗体中。

  • IDC – ActiveQt模块提供的命令行工具,用于将Qt二进制转化为COM server。 该工具由qmake调用,不需要手工执行。

  • dumpcpp – ActiveQt模块的命令行工具, 可以为一个类型库创建C++的命名空间。

  • dumpdoc – ActiveQt模块的命令行工具,可以为COM对象创建Qt风格的文档。

  • testcon – ActiveQt模块的命令行工具, 全称为ActiveX Test Container, 也就是可以作为ActiveX控件的容器, 这样可以把控件安装到系统中再测试。 该工具会提供详细的事件和属性变化的log信息。

  • Qt Script Debugger — 用于调试Qt Script的工具,可以单步运行,查看输出等。 Qt文档里有很详细的一篇专门讲这个的,有兴趣的来看下: Qt Script Debugger Manual

QT模块列表(官方清单)

https://doc.qt.io/qt-5/qtmodules.html

Qt Essentials

Qt Essentials定义了Qt在所有平台上的基础。它们可以在所有支持的开发平台和测试的目标平台上使用。除了测试模块将保持源代码兼容外,这些模块在整个Qt 5中都将保持源代码和二进制兼容。

基本模块是通用的,对大多数Qt应用程序都很有用。一个用于特殊用途的模块被认为是附加模块,即使它在所有支持的平台上都可用。

下表列出了Qt的基本模块。

Module Description
Qt Core Core non-graphical classes used by other modules.
Qt GUI Base classes for graphical user interface (GUI) components. Includes OpenGL.
Qt Multimedia Classes for audio, video, radio and camera functionality.
Qt Multimedia Widgets Widget-based classes for implementing multimedia functionality.
Qt Network Classes to make network programming easier and more portable.
Qt QML Classes for QML and JavaScript languages.
Qt Quick A declarative framework for building highly dynamic applications with custom user interfaces.
Qt Quick Controls Provides lightweight QML types for creating performant user interfaces for desktop, embedded, and mobile devices. These types employ a simple styling architecture and are very efficient.
Qt Quick Dialogs Types for creating and interacting with system dialogs from a Qt Quick application.
Qt Quick Layouts Layouts are items that are used to arrange Qt Quick 2 based items in the user interface.
Qt Quick Test A unit test framework for QML applications, where the test cases are written as JavaScript functions.
Qt SQL Classes for database integration using SQL.
Qt Test Classes for unit testing Qt applications and libraries.
Qt Widgets Classes to extend Qt GUI with C++ widgets.

Qt附加模块

Qt Add-On模块为特定目的带来了额外的价值。这些模块可能只在某些开发平台上可用。许多附加模块要么是功能完整的,为了向后兼容而存在,要么只适用于某些平台。每个附加模块都单独指定了其兼容性承诺。

Qt安装程序包括下载附加模块的选项。欲了解更多信息,请访问Qt入门页面。

下表列出了Qt附加组件。

Module Development Platforms Target Platforms Description
Active Qt Windows Windows Classes for applications which use ActiveX and COM
Qt 3D All All Functionality for near-realtime simulation systems with support for 2D and 3D rendering.
Qt Android Extras All Android Provides platform-specific APIs for Android.
Qt Bluetooth All Android, iOS, Linux, macOS, and UWP (*) Provides access to Bluetooth hardware.
Qt Concurrent All All (*) Classes for writing multi-threaded programs without using low-level threading primitives.
Qt D-Bus All All (*) Classes for inter-process communication over the D-Bus protocol.
Qt Gamepad All Android, iOS, macOS, tvOS (including the tvOS remote), Linux, Windows, and QNX Enables Qt applications to support the use of gamepad hardware.
Qt Graphical Effects All All Graphical effects for use with Qt Quick 2.
Qt Help All All (*) Classes for integrating documentation into applications, similar to Qt Assistant.
Qt Image Formats All All Plugins for additional image formats: TIFF, MNG, TGA, WBMP.
Qt Location All All Displays map, navigation, and place content in a QML application.
Qt Mac Extras All macOS Provides platform-specific APIs for macOS.
Qt NFC All Android and Linux (*) Provides access to Near-Field communication (NFC) hardware.
Qt OpenGL (Deprecated) All All (*) OpenGL support classes. Deprecated in favor of the QOpenGL* classes in the Qt GUI module.
Qt Platform Headers Qt for Windows, Linux, macOS Qt for Windows, Linux, macOS, Android (*) Provides classes that encapsulate platform-specific information, tied to a given runtime configuration of a platform plugin.
Qt Positioning All Android, iOS, macOS, Linux, UWP (*). Provides access to position, satellite and area monitoring classes.
Qt Print Support All All (*) Classes to make printing easier and more portable.
Qt Purchasing All Android, iOS, and macOS. Enables in-app purchase of products in Qt applications.
Qt Quick Controls 1 (Deprecated) All All (*) Reusable Qt Quick based UI controls to create classic desktop-style user interfaces. Deprecated in favor of Qt Quick Controls 2, which are better and easier to use.
Qt Quick Extras All All (*) Provides a specialized set of controls that can be used to build interfaces in Qt Quick.
Qt Quick Timeline All All (*) Enables keyframe-based animations and parameterization.
Qt Quick Widgets All All (*) Provides a C++ widget class for displaying a Qt Quick user interface.
Qt Remote Objects All All Provides an easy to use mechanism for sharing a QObject's API (Properties/Signals/Slots) between processes or devices.
Qt Script (Deprecated) All All Classes for making Qt applications scriptable. Deprecated in favor of the QJS* classes in the Qt QML module.
Qt SCXML All All Provides classes and tools for creating state machines from SCXML files and embedding them in applications.
Qt Script Tools (Deprecated) All All (*) Additional components for applications that use Qt Script.
Qt Sensors All Android, Qt for iOS, UWP, Mer, and QNX. Provides access to sensor hardware and motion gesture recognition.
Qt Serial Bus All Windows, Linux, Boot to Qt targets, and QNX. Provides access to serial industrial bus interface. Currently the module supports the CAN bus and Modbus protocols.
Qt Serial Port All Windows, Linux, macOS, and QNX. Provides access to hardware and virtual serial ports.
Qt Speech All All except QNX. Provides support for accessibility features such as text-to-speech.
Qt SVG All All Classes for displaying the contents of SVG files. Supports a subset of the SVG 1.2 Tiny standard.
Qt UI Tools All All (*) Classes for loading QWidget based forms created in Qt Designer dynamically, at runtime.
Qt WebChannel All All Provides access to QObject or QML objects from HTML clients for seamless integration of Qt applications with HTML/JavaScript clients.
Qt WebEngine All Windows, Linux, and macOS. Classes and functions for embedding web content in applications using the Chromium browser project.
Qt WebSockets All All Provides WebSocket communication compliant with RFC 6455.
Qt WebView All Platforms with a native web engine. Displays web content in a QML application by using APIs native to the platform, without the need to include a full web browser stack.
Qt Windows Extras All Windows Provides platform-specific APIs for Windows.
Qt X11 Extras All Linux/X11 Provides platform-specific APIs for X11.
Qt XML All All (*) C++ implementations of SAX and DOM.
Qt XML Patterns (deprecated) All All Support for XPath, XQuery, XSLT and XML schema validation.

在商业许可证或GNU通用公共许可证v3下提供的附加组件

Module Development Platforms Target Platforms Description
Qt Charts All All UI Components for displaying visually pleasing charts, driven by static or dynamic data models.
Qt Data Visualization All All UI Components for creating stunning 3D data visualizations.
Qt Lottie Animation All All A QML API for rendering graphics and animations in JSON format, exported by the Bodymovin plugin for Adobe® After Effects.
Qt Network Authorization All All Provides support for OAuth-based authorization to online services.
Qt Virtual Keyboard All Linux and Windows desktop, and Boot to Qt targets. A framework for implementing different input methods as well as a QML virtual keyboard. Supports localized keyboard layouts and custom visual themes.
Qt Wayland Compositor Linux Linux and Boot to Qt targets. Provides a framework to develop a Wayland compositor.
Qt for WebAssembly All Web browsers with WebAssembly support A platform target to compile Qt applications for the web browsers using WebAssembly.
Qt Quick 3D All All Provides a high-level API for creating 3D content or UIs based on Qt Quick.
Qt Quick WebGL All WebGL-enabled web browsers Provides a platform plugin that allows streaming Qt Quick user interfaces over the network using WebGL™.

增值模块

除了作为Qt 5一部分发布的模块外,以下模块和工具建立在Qt库的基础上,以提供额外的价值。它们有自己的发布时间表,并在商业许可下可用。

Feature Description
Qt Automotive Suite A collection of software components and tools to enable development of In-Vehicle-Infotainment (IVI) systems. Built on top of the Qt for Device Creation offering and compliant with the GENIVI automotive platform architecture.
Qt for Automation Libraries and tools for automation related domains, such as KNX, OPC UA, and MQTT.
Qt for Device Creation Tools for fast, easy, and fully-integrated embedded device application development. Included in most other value-add solutions.
Qt for MCUs Offers a complete graphics framework and toolkit with everything needed to design, develop, and deploy GUIs on microcontroller units (MCUs). Applications can run either on bare metal or on a real-time operating system.

Qt工具

Qt工具在所有支持的开发平台上运行,为应用程序的开发和设计提供便利。

下表列出了Qt工具。

Tool Description
Qt Designer Classes for extending Qt Designer.
Qt Distance Field Generator Generates distance field information for text entities in an application UI.

Qt实例和教程

https://doc.qt.io/qt-5/qtexamplesandtutorials.html

Qt提供了一系列的代码样本和教程,以帮助新用户开始使用Qt开发。这些文件涵盖了一系列的主题,从小工具的基本使用到一步步的教程,展示了一个应用程序是如何组合起来的。

这些例子是Qt软件包的一部分。请访问下载页面了解更多信息。

运行实例

在Qt Creator的欢迎模式下打开并运行例子。大多数例子都在不同的平台上运行,要搜索特定平台的例子,在搜索栏中输入平台名称(或任何关键字)。例如,在搜索栏中输入Android,会列出与Android完全兼容的例子。

关于在Qt Creator中运行例子的更多信息,请访问构建和运行一个例子的页面。

要查看所有Qt实例的列表,请访问List of Qt Examples页面。

参考

posted @ 2022-02-28 12:54  TaylorShi  阅读(2601)  评论(0编辑  收藏  举报