翻译自What about Qt 3D in Qt 6?
原文作者:Sean Harmer

在Qt 6中,我们希望可以在很多方面对Qt 3D进行改进,本文将着重介绍几个主要方向:渲染器工作缓存和现代图形API的支持,如Vulkan、Metal和DirectX 12。

渲染器缓存

Qt 3D的运行是基于两种现有的数据结构:

Scene Graph-描述场景的内容;
Frame Graph-描述渲染Scene Graph的方式。
每渲染一帧画面,我们必须做大量的工作,才能把scene graph和frame graph中的抽象描述转换为底层的draw调用并传送至GPU。简而言之,步骤如下:

  • 1.遍历frame graph并识别各个渲染阶段。每个阶段包括渲染target(屏幕或FBO);要使用哪个摄影机;要使用哪个窗口;应该绘制scene graph的哪些部分;设置GPU的特定状态(例如,禁用深度测试或写入,或启用模板测试)。
  • 2.步骤1中的每个渲染阶段都需要从scene graph中筛选出我们关心的实体。
  • 3.为每个实体以及当前渲染阶段选择相应的着色器。实体可以在不同阶段使用不同的着色器,例如,使用一个简单的片段着色器执行early Z填充或生成阴影贴图,而使用完全光照着色器实现屏幕上最终效果。
  • 4.合并uniform变量(用于自定义着色器中的变量)。
  • 5.将所有这些信息绑定到RenderCommands中。
  • 6.一旦所有阶段都完成了,我们将通过一个独立线程向OpenGL提交RenderCommands,由于OpenGL历史悠久,它对线程非常挑剔。
  • 7.OpenGL提交线程迭代各个渲染阶段和其中包含的命令,将它们从我们的中间描述翻译成OpenGL格式,并分派给原始的OpenGL函数调用。

这一切都使Qt 3D变得非常灵活,但代价是运行时的性能。通常能够大幅提升性能的方法无非就是通过缓存避免无谓的绘制开销。理论上,我们可以通过缓存一些中间结果来取得提升。而实际上,要考虑很多内容比如怎样结合动态渲染模式等,渲染器缓存确实很难做到。

这其中有太多可以影响渲染场景外观的东西需要跟踪,还要弄清楚当不同画面之间某些属性更新之后,必须重新绘制的最小任务集是什么。我们已经在Qt 5版本中添加了一些跟踪功能,但要完全做到这一点需要更大的重构。

在详细描述我们在这方面所做的工作之前,我先讨论另一个问题:

现代图形API

到目前为止,Qt Quick(基本上)已经完全架构在OpenGL(或OpenGL ES)之上,Qt 3D大抵如此。虽然OpenGL长期以来为图形工程师提供了很好的服务,但它是一个非常古老的API,有一些根生蒂固的结构性问题,以至于在不引入新API的情况下无法解决。此外,OpenGL经过多年的扩展和“改造”,试图跟上现代GPU的实际工作方式,并处理艺术家们所要求的、不断增长的数据量。尽管这促使OpenGL做了大量令人印象深刻的改进,但它仍然受到限制,特别是其多线程模型和驱动实现中的启发式模式,即驱动试图预测应用程序开发者的行为模式。

如上一节所述,在驱动程序内部,OpenGL的操作方式与Qt 3D非常相似。当您发出一堆OpenGL函数调用时,这些调用会被转换成命令并存储在命令缓冲区中,然后在某个时间点(由驱动程序的最佳预估决定)被提交给硬件进行处理。

一旦命令缓冲区中的命令被硬件处理掉,下一帧我们必须再次发出OpenGL函数调用。同样的流程会一帧接一帧地发生,这可非常浪费。

在驱动中,创建命令是一项非常耗资源的操作,而且在OpenGL中,这一切都被限制在一个线程内。所以,清空命令缓冲区有点浪费。编写驱动的GPU厂商添加了各种启发算法,试图预测库和应用程序开发者实际的意图,藉此尽可能缓存数据并优化操作。这使得驱动变得更大、更复杂、更难维护,并在某些情况下导致GPU厂商之间的巨大性能差异。

OpenGL的线程模型本质上是单线程的。是的,可以通过共享context等一些方式支持多线程,但在驱动内部调用仍然会被序列化。考虑到OpenGL已有20多年的历史,这并不奇怪。

OpenGL标准陈旧是另一个问题。苹果公司已宣布弃用OpenGL,将只专注于将Metal作为其图形API。在未来的某个时候,我们可能会发现OpenGL从MacOS和iOS中消失。即使在那之前,这些平台上的OpenGL库也不会看到任何新的功能了(事实上,它们已经很多年没有更新了)。

对于这些问题我们能做什么?好吧,在过去几年中,现代图形API的出现就是用于解决这些和其他问题的。Vulkan、Metal和DirectX 12都是非常流行的API,与OpenGL相比,它们提供了更直接控制GPU的接口。
您可能会说这太好了,但其实存在妥协之处。OpenGL驱动程序所做的大部分工作现在由库或应用程序开发者负责。乍听上去很吓人,然而在某种程度上的确如此。但是,毕竟我们可以利用自己对应用程序工作模式的宏观理解从GPU中榨取性能。另一方面我们可以选择在更短的时间内完成类似的工作,从而让CPU/GPU进入休眠或省电模式,最终提高续航表现。这对于移动设备和台式机而言都是巨大的提升。

OpenGL驱动程序将丢弃命令缓冲区,而且它在每一帧上的创建消耗都很高,但是当我们作为应用程序开发者使用Vulkan或类似工具时,我们可以知道何时保留这些命令缓冲区并在下一帧重新提交它们是安全的。

您可能想知道那有什么好处。提交相同的命令缓冲区只能让我们在屏幕上看到与前一帧完全相同的内容,难道不是吗?如果是的话,那这么做有什么意义呢?

这是好问题。其实即使我们一次又一次地向GPU提交相同的命令缓冲区,它们引用的资源却可以包含不同的数据。不仅是顶点缓冲区和纹理,还可以包括通常用于保存材质属性和相机变换矩阵的uniform缓冲区对象。如果我们能够跟踪场景中哪些东西发生变化,就能确定是否可以将相同的命令重新提交给GPU,从而节省大量工作,这就非常棒。

还有一个锦上添花的情况!Vulkan使用了主命令缓冲区和辅命令缓冲区的概念。主命令缓冲区是我们提交给GPU的内容,可能包含对辅命令缓冲区的调用。一种常见的使用方式是预先记录某些实体的绘制命令并保存到辅命令缓冲区。

当我们想要绘制整个场景时,我们的渲染器可以创建一个主命令缓冲区,调用那些可见实体的命令缓冲区。当可见性改变时(例如,如果相机移动或某些实体移动),我们可以重新记录主命令缓冲区。那也很好。

更多的锦上添花!使用Vulkan,我们还可以在不同线程上读写命令缓冲区!我们来负责向GPU队列提交命令缓冲区,并在不同的GPU队列(图形/计算/传输等)之间以及GPU和CPU之间同步任务。

如您所见,我们可以在所涉及的操作和硬件上获得更多的控制,但我们必须做更多的工作。总的来说,这是一个巨大的性能提升机会。

继续聊Qt 6中的Qt 3D

以Qt 6开发时间节点来看,我们正积极研究这两个大方向。从以上描述可以看出,这两项任务都涉及大量工作,关于如何跟踪用户在scene graph和frame graph上状态的修改以及接下来Qt 3D必须完成的剩余工作。这包括我们如何最终缓存命令缓冲区以及帧之间的其他中间状态,以避免不必要的重复工作。

正如您可能已经了解,Qt Quick和Qt Quick 3D会在QRhi层基础上重新构建,QRhi层提供对Vulkan、Metal、DirectX 11和OpenGL的支持。我们仍在研究它是否可以合理扩展此功能以满足Qt 3D在功能和多线程方面的需求,或者是否需要使用其他方式集成图形API,这样Qt 3D仍然可以很好地与Qt Quick和Qt Widgets模块配合使用。

这方面还有很多工作要做,但初步结果看起来非常有希望。我们测试了包含大约1000个实体的场景,在一个中档桌面平台上当我们试图最大化利用GPU时,可以实现每秒600帧(画面无撕裂)的渲染速度,或者当我们限制到60fps时,可以实现1%的CPU负载占用!现在这还只使用了单个内核!为了进一步改进多线程架构,超越Qt 5系列的极限,我们正在验证一些想法。

这项工作有一个副产品,我们还开发出了frame graph的下一个迭代版本,它的更新非常自然平滑,因此更加容易理解,也更易于Qt 3D用户的修改。

总结

如您所见,在Qt 5.x周期及以后的时间里,我们会在幕后做许多工作改进Qt 3D。我们还将寻找改进public API的方法,但我们预计在这方面不会有太大的变化,而是对一些不太理想的函数名和属性名进行一些清理。
所有这些改进也将有利于基于Qt 3D的Kuesa和其他任何使用Qt 3D开发的3D应用程序。这些变化将帮助打造一个坚实的基础,使我们可以在Qt 6时加入更多令人兴奋的扩展。

原文地址

Qt 6的Qt 3D会是什么样?相关推荐

  1. Qt Quick 3D介绍:Qt Quick的高级3D API

    目录 我们的目标是什么?为什么提出另一个3D解决方案? 统一图形技术 直观易用的API Qt Quick的统一工具 一流的素材优化管道 跨平台性能和兼容性 Qt Quick 3D到底是什么? 您能用Q ...

  2. 与Qt结合使用的3D引擎

    转载地址 https://wiki.qt.io/Using_3D_engines_with_Qt Ogre Ogre Website QtOgre QML Ogre Irrlicht Irrlicht ...

  3. QT与OGRE做3D地图编辑器

    http://blog.163.com/modingfa_002/blog/static/1109254662010427114343461/ http://download.chinaprj.cn/ ...

  4. 【Qt OpenGL】Qt Creator中的3D绘图及动画教程

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  5. Qt OpenGL 加载3D世界,并在其中漫游

    这次教程中,我将教大家如何加载一个3D世界,并在3D世界中漫游.这相较于我们只能创造一个旋转的立方体或一群星星时有很大的进步了,当然这节课代码难度不低,但也不会很难,只要你跟着我慢慢一步一步来. 一个 ...

  6. Qt Design Studio的3D编辑器

    本文翻译自:Meet Qt Design Studio 3D Editor 原文作者:Mahmoud Badri 校审:Richard Lin 在Qt Design Studio 1.4中,我们首次实 ...

  7. OpenGL(十八)——Qt OpenGL绘制一个3D世界

    OpenGL(十八)--Qt OpenGL绘制一个3D世界 一.说明 本篇介绍构建一个3D的世界. 二.简介 加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游. ...

  8. Qt Creator开发Qt快速应用程序

    Qt Creator开发Qt快速应用程序 开发Qt快速应用程序 创建Qt快速项目 在设计模式下编辑QML文件 创建UI 添加动态 编辑3D场景 相关话题 浏览ISO 7000图标 将QML模块与插件一 ...

  9. QT简介及QT环境搭建

    QT简介及QT环境搭建 文章目录 QT简介及QT环境搭建 一.QT简介 1. 什么是QT? 2. QT的发展史 3. QT支持的平台 4. QT的优点 5. QT开发工具 二.QT环境搭建(CentO ...

最新文章

  1. openGL 入门 2--顶点数组对象 VAO 和 缓存对象 VBO
  2. html弹窗赋值给查询框,bootstrap模态框动态赋值, ajax异步请求数据后给id为queryInfo的模态框赋值并弹出模态框(JS)...
  3. 10.QT事件机制源码时序分析(中)
  4. linux 分区_Linux文件系统、逻辑分区、物理分区
  5. Oracle ASM 详解
  6. 多线程安全问题产生解决方案
  7. linuxpython23同时_Linux-centos同时存在Python2-Python3
  8. 2017 济南综合班 Day 2
  9. 使用 IntraWeb (26) - 基本控件之 TIWMenu
  10. 一个功能强大超级好用的图表组件Dundas Chart
  11. 日常的SQL 语句使用
  12. Vmware使用net模式共享虚拟机linux IP
  13. android离线身份证识别(从相册选择)
  14. 人事档案的重要性及注意事项
  15. 指针生成网络(Pointer-Generator Networks)的实现
  16. oracle数据库exec用法,Sql中exec的用法
  17. 【STM32】时钟系统及其结构原理
  18. recyclerView + editTextView 编辑图片和文字标题 问题
  19. 6-1 求实数和的函数
  20. vs 项目重新生成无反应,仍然执行之前原先代码

热门文章

  1. 技术干货 | JavaScript 之事件循环(Event Loop)
  2. 网易云信独家技术支持,壹点灵领跑心理服务行业
  3. 在创业公司,不懂运维的程序员如何兼顾公司的运维工作
  4. jqueryeasyui datebox 设置默认值
  5. 安全测试需要关注那些要点
  6. 调用WebService时加入身份验证,以拒绝未授权的访问
  7. tfrecord文件生成与读取
  8. HTML基础,块级元素/行内元素/行内块元素辨析【2分钟掌握】
  9. Ubuntu 安装 QQ
  10. 解析Markdown文件生成React组件文档