Qt Vulkan支持及Qt界面技术简析

2017-12-18

  本来计划在Qt5.9版本支持Vulkan的,但是跳水了一个版本,放到了Qt5.10。估计是因为5.9是长期支持版,怕vulkan带来了不稳定性。经过了一周时间的延后,正式版本还是发布了。似乎Qt Vulkan支持一直是 Laszlo Agocs 负责的(没有验证),最高的实验版本也是他给出的。
  OpenGL很早就成为了Qt的渲染核心,我想在可见的将来,应该也不会替换成其他的渲染API。但是,Qt还是尝试了可替换渲染API的集成,更早的D3D12,现在的Metal,Vulkan。
  我们知道OpenGL,D3D,Vulkan这样的API,对接的是操作系统底层的窗口对象,在win32,linux,macOS等上都有类似surface的概念。我们可以把surface理解为显示器上一块矩形像素区域。虽然我们在使用win32接口创建窗口时并不会见到surface的概念,但是,我们可以把HWND hWnd = CreateWindow(***) 理解为surface的简单封装,加上了minimize、close、icon、title等显示区域和功能。相反,在Linux 系统中,xlib 提供了Window对象(minimize、close按钮),和win32 API一样不负责任何绘制操作,cairo 库则是让surface封装了Window对象,负责绘制窗口系统,Qt则似乎是自己用QPainter、QPaintDevice等实现了cairo、gdi+等绘制二维图形的功能(待验证)。总体上来说,surface的概念,就是一块矩形像素,你可以自己操作像素来绘制二维,甚至三维图像(),它和窗口系统系统的事件无关。

  

  此图也表明了Qt自己重新实现了二维绘制算法。另有文章 。Vulkan现在有6中窗口拓展:

 

Extension Name

Required Compile Time Symbol

Window System Name

External Header Files Used

VK_KHR_android_surface

VK_USE_PLATFORM_ANDROID_KHR

Android Native

<android/native_window.h>

VK_KHR_mir_surface

VK_USE_PLATFORM_MIR_KHR

Mir

<mir_toolkit/client_types.h>

VK_KHR_wayland_surface

VK_USE_PLATFORM_WAYLAND_KHR

Wayland

<wayland-client.h>

VK_KHR_win32_surface

VK_USE_PLATFORM_WIN32_KHR

Microsoft Windows

<windows.h>

VK_KHR_xcb_surface

VK_USE_PLATFORM_XCB_KHR

X Window System Xcb library

<xcb/xcb.h>

VK_KHR_xlib_surface

VK_USE_PLATFORM_XLIB_KHR

X Window System Xlib library

<X11/Xlib.h>

  在Qt中,我们需要把Vulkan渲染的结果放到一个QSurface中。QWindow再封装QSurface。在Qt中继承关系为:
   class Q_GUI_EXPORT QWindow : public QObject, public QSurface
   class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
  QWindow是一个偏底层的概念。而QWidget在QtWidgets module,是一个高于core和 gui 的模块。 因为QWindow很底层,我们不能再随意的在QWindow上添加各种控件。所以,我们一般只想用它来绘制纯渲染内容。 比如,我们最常用的QOpenGLWidget,它的定义是 class Q_WIDGETS_EXPORT QOpenGLWidget : public QWidget,QVulkanWindow则是 QtGui module的概念,比QtWidgets模块低一个层次。如果我们需要一个Vulkan Widget,可以非常简单的实现出来:QWidget *wrapper = QWidget::createWindowContainer(QVulkanWindow *); 对于任何Vulkan项目,我们只需要引入默认的QtGui 模块即可。
  对QOpenGLWindow,QVulkanWindow,我们不需要QPaintDevice和QPainter所抽象出来的绘制各种二维简单图形并显示的功能,所有的一切我们都将使用OpenGL、D3D或者Vulkan来绘制,绘制的内容传递到操作系统层面的窗口(surface)上。所以,把Vulkan和窗口系统结合起来不是那么复杂的工作。glfw早就做好了。API 函数指针解析是独立的一个模块,如果我们不使用第三方的OpenGL加载lib,那么我们就只能使用OpenGL1的功能。类似的,如果我们不使用Qt给出的VulkanWindow抽象,我们也需要自己使用单独的lib来获取vulkan函数的指针。 
  Vulkan程序非常简单,只需要一个instance,一个支持vulkan的窗口,和一个renderer对象。多个窗口可能共享一个renderer对象,多个窗口可能共享一个instance对象。绝大多数应用只会用到单显卡,所以也不用考虑物理设备问题。
  5.10 的安装包提供了5个Vulkan Example,在Qt Creator中搜索不到,但是在安装目录下有。也可用vs导入pro项目,需要做一些下的修改。Qt官方站点需要注册才能获取下载链接,这实在是有点烦人。除了给我们邮箱发送一些新闻,也不能做什么其他的事情了。却需要我们记忆一个帐号。但是Qt还是保留了直接下载页面的。https://download.qt.io/,只是需要自己找一下。
  至于vs的qt插件,很早就更换了安装方式,从vs add-in变成了vs tools。支持vs 2015和2017。可从如下链接下载:https://download.qt.io/official_releases/vsaddin/
  似乎vs tools和 vs 2015之间协作还是有些问题,用vs直接创建的工程不能正确的找到vulkan相关头文件,可能和没有正确解析VULKAN_SDK 环境变量有关。没有关系,我们手动添加上vulkan include文件夹即可。由于我们并不需要链接vulkan的lib,所有的vulkan api都是运行时从dll中解析出来的。所以,只需要头文件和安装了vulkan sdk即可。当然了,我们也是可选链接vulkan lib的。

  1. http://blog.qt.io/blog/2017/06/06/vulkan-support-qt-5-10-part-1/
  2. http://blog.qt.io/blog/2016/01/28/qt-and-direct3d-12-first-encounter/
  3. http://blog.csdn.net/fuyajun01/article/details/9246231
  4. https://stackoverflow.com/questions/17860604/what-is-the-difference-between-a-qwindow-and-qwidget
  5. https://msdn.microsoft.com/en-us/library/bb384843.aspx 

Q1:Cannot run compiler 'cl'. Maybe you forgot to setup the environment?
A:    需要把vs 2015 的cl.exe 所在路径添加到PATH

12.18  P.S. 本来是只想写Qt Vulkan的东西,发现能写的实在不多,就把以前做的关于QWindow、QWidget的笔记整理了一下。跑步一个多小时,出出汗,近十点半到家,感觉还是挺舒服的。
12.20 后续文章再仔细写技术细节吧。

如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)