Skip to main content

在Vulkan、Metal和Direct3D上运行Qt Quick-第2部分

Comments

本文翻译自Qt Quick on Vulkan, Metal, and Direct3D - Part2

原文作者:Laszlo Agocs,Qt公司高级开发工程师

校审:Richard Lin

让我们接着第一篇文章开始讲。前面我们看到了Qt Quick应用程序在Linux下面基于OpenGL和Vulkan运行的示例。我们也看到在RenderDoc中捕获Vulkan帧的示例,这不仅仅是Qt开发中的重要工具,对于想挖掘深层次的原理并更好地理解Qt Quick是如何在应用中渲染帧 (或排除渲染的故障)也是非常有用的。在这篇文章中,我们将重点关注Qt 5.14为macOS和Windows提供了什么功能。

macOS上的Metal

在macOS 10.13或10.14设置QSG_RHI=1(以及QSG_INFO=1)并运行qt5-cinematic-experience 示例程序,可以看到如下的结果:

cinematic_metal

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(同时也允许应用程序选择其他图形API),在macOS上启用QRhi的渲染方式后,系统会默认使用Metal来渲染Qt Quick。

类似于在QtGui、QPA,和其他一些平台插件中添加Vulkan实例和Surface构建Vulkan渲染后台的方式,QRhi的Metal后台依赖于Qt 5.12前后引入的cocoa平台插件中的Metal的支持。带QSurface::MetalSurface标志的QWindow将获得一个NSView,NSView背后是一个CAMertalLayer。这就是QRhi的Metal后端架构。(要使能QRhi的渲染路径,并且QQuickWindow获得正确的QSurface::SurfaceType标记值,才能正常运行)

有一个非常重要的特性,即能够使用独立的渲染线程运行Qt Quick。之前由于macOS 10.14中的NSOpenGLContext以及相关API中存在一个的多线程问题,Qt在macOS上禁用了独立的OpenGL渲染线程,而把默认值改为“basic”。这导致Qt Quick动画的平滑度有所降低。对于Metal,我们没有(根据我们目前的认知)发现任何多线程的问题,因此我们又可以开启独立的渲染线程了。(通过设置QSG_RENDER_LOOP环境变量,可以改写渲染线程的设置;这个变量可与QSG_RHI配合使用)

我们之前提到了RenderDoc,它可以调试Qt应用程序的帧渲染,支持OpenGL、Vulkan以及Direct3D的运行态。对于Metal,可以使用XCode及其内置的GPU帧快照器。

xcode_framecapture

有一个实用方法可以用XCode快速打开待调试的Qt项目,在命令行执行make xcodeproj && open *.xcodeproj(如果还没有执行qmake则可以执行qmake -spec macx-xcode)。按下Cmd-R,然后会立即启动调试器。在Qt开发期间我们会经常这样使用。为了防止Metal GPU获取失败,即使Qt Quick已经设置为Metal渲染,还是要检查 “Product ->Scheme->Edit scheme…”,并将GPU帧获取获改为Metal。

xcode_product_scheme_editscheme

在XCode中调试构建应用程序时会启用Metal验证,这意味着当Metal API使用不当时,XCode将(理想情况下)返回提示性警告并中断程序执行。与其他平台不同的是,如果不通过XCode进行调试,则无法启用Metal API验证。(与Vulkan和D3D不同,设置环境变量QSG_RHI_DEBUG_LAYER无效)

iOS上的Metal

iOS或者tvOS上是什么情况?

在编写本文时,(iOS和tvOS的)平台插件中缺少与Metal相关的管道,这也意味着QRhi的Metal后端还没有在这些平台上进行测试。这就是为什么Qt 5.14新特性页面关于Qt Quick的部分只提到macOS。预计在不久的将来,可能5.15中,会增加相关的支持。

macOS上的Vulkan

如何通过MoltenVK使用Vulkan呢?

正如在第1部分中提到的,使用Vulkan发起渲染,然后依靠MoltenVK在运行时将API调用和SPIR-V着色器代码转换为Metal和Metal着色语言也是一种选择。这需要一个支持Vulkan的Qt库,这在Apple平台上不是现成提供的。有关详细信息,请参阅这篇文章,关键是使用configure参数-I来设置并确保可以在运行时使用环境变量QT_VULKAN_LIB并找到对应的库。

必须要注意,这个方式(在macOS上通过MoltenVK使用Vulkan)只是“尽我们能力”去支持。在Apple平台上首要的渲染方式是通过Metal

使用QSG_RHI_BACKEND=vulkan (使用适当配置的Qt 5.14库)运行演示应用程序,结果如下:

mvk

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的Mac Mini和一个半新版本的Vulkan SDK / MoltenVK上,结果却非常好,正如屏幕截图所示。

Windows平台

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

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

目前还没有D3D12的后台。以后会增加它因为有这个计划,但目前还没有实施。回到我们的主题,需要注意一件事,在Qt 5.8中添加的实验性质的Qt Quick的D3D12直接渲染后端在Qt 6中被弃用了(因为我们会以一种全新的方式来解决多图形API的问题)。

在Windows上设置QSG_RHI=1时的默认值是Direct3D 11。与往常一样,如果需要Vulkan或OpenGL,则需要使用QSG_RHI_BACKEND进行修改。

cinematic_d3d11

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,需要注意,目前基于D3D11的渲染后台在Qt 5.14的Windows 7上不能正常工作,因此在5.14的新特性页面上只提到了Windows 10。这是以后需要补充的地方(但前提是Qt6仍然会支持Windows 7)。

要启用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应用程序的所有内容,在新的渲染平台上都有。(比如desktop, ANGLE, Software三选一参数以及各种环境变量,如QT_OPENGL

说到ANGLE,我们的期望在Qt6中把它从直接依赖库中删除。这需要进一步调查以完全确保我们不会失去对特殊用例的支持,但是现在的计划是让QRhi-based渲染路径在Windows上支持Direct3D 11、OpenGL(通过WGL)和Vulkan,这就已经能够满足应用开发了。

这就是这篇文章的全部内容。在第3部分中,我们将最终开始深入研究QRhi是什么以及如何处理着色器。

Comments

Subscribe to our blog

Try Qt 6.11 Now!

Download the latest release here: www.qt.io/download

Qt 6.11 is now available, with new features and improvements for application developers and device creators.

We're Hiring

Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.